chuck-1.2.0.8.dfsg/0000755000175000017500000000000010612370750012346 5ustar piempiemchuck-1.2.0.8.dfsg/AUTHORS0000644000175000017500000000135410600421722013412 0ustar piempiem--- ChucK is originated by: Ge Wang (gewang@cs.princeton.edu) Perry R. Cook (prc@cs.princeton.edu) Lead Design: Ge Wang Perry Cook Developers: Ge Wang (Lead) Perry Cook Ananya Misra (amisra@cs.princeton.edu) Philip Davidson (philipd@alumni.princeton.edu) Ari Lazier (alazier@cs.princeton.edu) Spencer Salazar (ssalazar@cs.princeton.edu) Rebecca Fiebrink (fiebrink@cs.princeton.edu) Dan Trueman (dan@music.princeton.edu) Lead Test: Philip Davidson Ajay Kapur Ge Wang Documentation: Adam Tindale Philip Davidson Ananya Misra Spencer Salazar Ge Wang (See also the file THANKS and README) --- ChucK home page: http://chuck.cs.princeton.edu/ Princeton Sound Lab: http://soundlab.cs.princeton.edu/ chuck-1.2.0.8.dfsg/COPYING0000644000175000017500000004310310600421722013373 0ustar piempiem GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 Library General Public License instead of this License. chuck-1.2.0.8.dfsg/DEVELOPER0000644000175000017500000000024510600421722013610 0ustar piempiem--- ChucK Developer's Guide current version of this document: http://chuck.cs.princeton.edu/doc/develop/ chuck home: http://chuck.cs.princeton.edu/ --- chuck-1.2.0.8.dfsg/doc/0000755000175000017500000000000010600421764013112 5ustar piempiemchuck-1.2.0.8.dfsg/doc/ChucK_manual.pdf0000644000175000017500000222472410600416351016150 0ustar piempiem%PDF-1.4 5 0 obj << /S /GoTo /D (section*.1) >> endobj 8 0 obj (Authors of ChucK) endobj 9 0 obj << /S /GoTo /D (section*.2) >> endobj 12 0 obj (ChucK Places) endobj 13 0 obj << /S /GoTo /D (chapter.1) >> endobj 16 0 obj (Intro-ChucK-tion) endobj 17 0 obj << /S /GoTo /D (chapter.2) >> endobj 20 0 obj (Installation) endobj 21 0 obj << /S /GoTo /D (section*.7) >> endobj 24 0 obj (Binary Installation) endobj 25 0 obj << /S /GoTo /D (section*.10) >> endobj 28 0 obj (Source Installation) endobj 29 0 obj << /S /GoTo /D (chapter.3) >> endobj 32 0 obj (ChucK Tutorials) endobj 33 0 obj << /S /GoTo /D (section*.11) >> endobj 36 0 obj (A Chuck Tutorial) endobj 37 0 obj << /S /GoTo /D (section*.13) >> endobj 40 0 obj (Conventions) endobj 41 0 obj << /S /GoTo /D (section*.17) >> endobj 44 0 obj (On-the-fly-programming) endobj 45 0 obj << /S /GoTo /D (section*.20) >> endobj 48 0 obj (Modifying Basic Patches) endobj 49 0 obj << /S /GoTo /D (section*.21) >> endobj 52 0 obj (LFOs and Blackhole) endobj 53 0 obj << /S /GoTo /D (section*.22) >> endobj 56 0 obj (Working with MIDI) endobj 57 0 obj << /S /GoTo /D (section*.25) >> endobj 60 0 obj (Writing To Disk) endobj 61 0 obj << /S /GoTo /D (section*.26) >> endobj 64 0 obj (Stereo) endobj 65 0 obj << /S /GoTo /D (chapter.4) >> endobj 68 0 obj (Overview) endobj 69 0 obj << /S /GoTo /D (section*.28) >> endobj 72 0 obj (running ChucK) endobj 73 0 obj << /S /GoTo /D (section*.29) >> endobj 76 0 obj (comments) endobj 77 0 obj << /S /GoTo /D (section*.30) >> endobj 80 0 obj (debug print) endobj 81 0 obj << /S /GoTo /D (section*.31) >> endobj 84 0 obj (reserved words) endobj 85 0 obj << /S /GoTo /D (chapter.5) >> endobj 88 0 obj (Types, Values, and Variables) endobj 89 0 obj << /S /GoTo /D (section*.32) >> endobj 92 0 obj (primitive types) endobj 93 0 obj << /S /GoTo /D (section*.33) >> endobj 96 0 obj (values \(literals\)) endobj 97 0 obj << /S /GoTo /D (section*.34) >> endobj 100 0 obj (variables) endobj 101 0 obj << /S /GoTo /D (section*.35) >> endobj 104 0 obj (reference types) endobj 105 0 obj << /S /GoTo /D (chapter.6) >> endobj 108 0 obj (Arrays) endobj 109 0 obj << /S /GoTo /D (section*.36) >> endobj 112 0 obj (declaration) endobj 113 0 obj << /S /GoTo /D (section*.37) >> endobj 116 0 obj (multi-dimensional arrays) endobj 117 0 obj << /S /GoTo /D (section*.38) >> endobj 120 0 obj (lookup) endobj 121 0 obj << /S /GoTo /D (section*.39) >> endobj 124 0 obj (associative arrays) endobj 125 0 obj << /S /GoTo /D (section*.40) >> endobj 128 0 obj (array assignment) endobj 129 0 obj << /S /GoTo /D (chapter.7) >> endobj 132 0 obj (Operators and Operations) endobj 133 0 obj << /S /GoTo /D (section*.41) >> endobj 136 0 obj (cast) endobj 137 0 obj << /S /GoTo /D (chapter.8) >> endobj 140 0 obj (Control Structures) endobj 141 0 obj << /S /GoTo /D (section*.42) >> endobj 144 0 obj (if / else) endobj 145 0 obj << /S /GoTo /D (section*.43) >> endobj 148 0 obj (while) endobj 149 0 obj << /S /GoTo /D (section*.44) >> endobj 152 0 obj (until) endobj 153 0 obj << /S /GoTo /D (section*.45) >> endobj 156 0 obj (for) endobj 157 0 obj << /S /GoTo /D (section*.46) >> endobj 160 0 obj (break / continue) endobj 161 0 obj << /S /GoTo /D (chapter.9) >> endobj 164 0 obj (Functions) endobj 165 0 obj << /S /GoTo /D (section*.47) >> endobj 168 0 obj (writing) endobj 169 0 obj << /S /GoTo /D (section*.48) >> endobj 172 0 obj (calling) endobj 173 0 obj << /S /GoTo /D (section*.49) >> endobj 176 0 obj (overloading) endobj 177 0 obj << /S /GoTo /D (chapter.10) >> endobj 180 0 obj (Concurrency and Shreds) endobj 181 0 obj << /S /GoTo /D (section*.50) >> endobj 184 0 obj (sporking shreds \(in code\)) endobj 185 0 obj << /S /GoTo /D (section*.51) >> endobj 188 0 obj (the 'me' keyword) endobj 189 0 obj << /S /GoTo /D (section*.52) >> endobj 192 0 obj (using Machine.add\(\)) endobj 193 0 obj << /S /GoTo /D (section*.53) >> endobj 196 0 obj (inter-shred communication) endobj 197 0 obj << /S /GoTo /D (chapter.11) >> endobj 200 0 obj (Time and Timing) endobj 201 0 obj << /S /GoTo /D (section*.54) >> endobj 204 0 obj (time and duration) endobj 205 0 obj << /S /GoTo /D (section*.55) >> endobj 208 0 obj (operations on time and duration \(arithmetic\)) endobj 209 0 obj << /S /GoTo /D (section*.56) >> endobj 212 0 obj (the keyword `now') endobj 213 0 obj << /S /GoTo /D (section*.57) >> endobj 216 0 obj (advancing time) endobj 217 0 obj << /S /GoTo /D (chapter.12) >> endobj 220 0 obj (Events) endobj 221 0 obj << /S /GoTo /D (section*.61) >> endobj 224 0 obj (what they are) endobj 225 0 obj << /S /GoTo /D (section*.62) >> endobj 228 0 obj (use) endobj 229 0 obj << /S /GoTo /D (section*.63) >> endobj 232 0 obj (MIDI events) endobj 233 0 obj << /S /GoTo /D (section*.64) >> endobj 236 0 obj (OSC events) endobj 237 0 obj << /S /GoTo /D (section*.65) >> endobj 240 0 obj (creating custom events) endobj 241 0 obj << /S /GoTo /D (chapter.13) >> endobj 244 0 obj (Objects) endobj 245 0 obj << /S /GoTo /D (section*.66) >> endobj 248 0 obj (introduction) endobj 249 0 obj << /S /GoTo /D (section*.67) >> endobj 252 0 obj (built-in classes) endobj 253 0 obj << /S /GoTo /D (section*.68) >> endobj 256 0 obj (working with objects) endobj 257 0 obj << /S /GoTo /D (section*.69) >> endobj 260 0 obj (writing a class) endobj 261 0 obj << /S /GoTo /D (section*.70) >> endobj 264 0 obj (members \(instance data + functions\)) endobj 265 0 obj << /S /GoTo /D (section*.71) >> endobj 268 0 obj (class constructors) endobj 269 0 obj << /S /GoTo /D (section*.72) >> endobj 272 0 obj (static \(data + functions\)) endobj 273 0 obj << /S /GoTo /D (section*.73) >> endobj 276 0 obj (inheritance) endobj 277 0 obj << /S /GoTo /D (section*.74) >> endobj 280 0 obj (Overloading) endobj 281 0 obj << /S /GoTo /D (chapter.14) >> endobj 284 0 obj (The ChucK Compiler + Virtual Machine) endobj 285 0 obj << /S /GoTo /D (chapter.15) >> endobj 288 0 obj (On-the-fly Programming Commands) endobj 289 0 obj << /S /GoTo /D (chapter.16) >> endobj 292 0 obj (Standard Libraries API) endobj 293 0 obj << /S /GoTo /D (chapter.17) >> endobj 296 0 obj (Unit Generators) endobj 297 0 obj << /S /GoTo /D [298 0 R /Fit ] >> endobj 301 0 obj << /Length 581 /Filter /FlateDecode >> stream xڭTn0+xZ.=m(Їuď6}(Ӡ@!pPRGVej!れ'JkP_o:9R:-U.󺸪/u0Ŕ!B5}.2UbdH[剌$+N"t}F( dO4)NHOef OSw?6Bi,A{c/_Ч|M!0,I[sg|Ue@Z Z@mjuhx;2,srcvMU0M&ow0j:߭W0uXztH4TZўɫJ8F6QD,j?N\҄Ҡ(Qyz܊4:#4Irui;pѧ]?RvyiE~X-W鬝N; dF'kiާ{ c;endstream endobj 298 0 obj << /Type /Page /Contents 301 0 R /Resources 300 0 R /MediaBox [0 0 612 792] /Parent 315 0 R /Annots [ 310 0 R ] >> endobj 299 0 obj << /Type /XObject /Subtype /Image /Width 200 /Height 180 /BitsPerComponent 8 /Length 15525 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream JFIFHHPhotoshop 3.08BIM ResolutionHH8BIM FX Global Lighting Angle8BIMFX Global Altitude8BIM Print Flags 8BIM Copyright Flag8BIM'Japanese Print Flags 8BIMColor Halftone SettingsH/fflff/ff2Z5-8BIMColor Transfer Settingsp8BIM Layer State8BIM Layer Groups8BIMGuides@@8BIM URL overrides8BIMSlicesu chuck_logo8BIMICC Untagged Flag8BIMLayer ID Generator Base8BIM New Windows Thumbnail peP JFIFHHAdobed            ep"?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?TI%)%;# { Ouip:~Ucz?C%u?/λgO?^?C%u?/λgO?^?C%Հvlcge+&xfͅ$;wC`=?o?%pϠ.޻Ycv`l|jUꜬ7:a?k}]郦ಆ$y.vsIV*/lh k:^.Q-)_ЪoYKen2I1C5\{lvGOϢ| KU/յ򐖰ߢXnL[S&>3YKU軏Yڇ4!Q9>C1<}8³0\/Udž돸U%1Vzݣ"OȨK oxdԿt7QvOE@#3$C%TmybZQp 1{S-yxMUr(K ڜu%{[Kk|ܡHVпV?Y5dPZI'ȶ}ɋt-DU_l'\ԜP%c\kiݻ"_kZ;~3{8 vi2r78xVrO|moG sI"4{?K|^o! "g_ ?b@Q|sľ,<3FUN?n1mϫXKeRO$YS+ 9n^G~Ǧ?ƌ\!.9}7& ސO%(F,gYYAaS옞ԯ+~KW1upT?{^>{I~J?6 z_RxKԯ5wI/{I^ÃPEmxӭ'ggy_~Ґ%t=kvd+,03L)ŏ&Fe9C?cɿ۰I)_Tʩ$ꤗʩ$ꤗʩ$ꤗʩ$ꤗʩ$ꤗʩ$ꤗʩ$8BIM!Version compatibility infoUAdobe PhotoshopAdobe Photoshop 6.08BIM JPEG QualityAdobed@        s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?v*UثWb]v*UثWb]v*UثWb]v*Uie^*nadkP1W}j*Ax]?߃}w֠~bUZ>P1W}j*Ax]?߃}o0`UA"7F_v*Uv*-+jFRkGnbGpJ*7]C:%8cccGYXpP򞙫~ku5Q^ =8/Uǧ+yꆛ=40G$D1=h뽛jgZ9 H;mrh|Ⱥӛ;w!8~?_qCBGB-1(SoȺӏJ?oُB>O.EoPQ~zr.+}4}?ҏ[cPˑuq[;w!/߳?}ޟ\8k!)7]Vi]E Ow"N?w(C(_f? ??_qCBGB-1(SoȺӏJ?oُB>O.EoPQ~?_qCBGB-1(Sֆ?Y7J@ok!)7:޳ 6jnyK<L:FOA7U@lxG6n;/CϤ2"ڠcvN}i0pk'v*Uv*ri<ʺ?TSWliܖmwOM2]'*?sWj?KDw:_!|*!|*!|*!|*!|*!|X>g!8x?#6(?DI_o{u y{$'gbb]v*r+b9tCXg@nnKy" G`+A^*vݟ_YIa`YNٝv-ia͘#-:GM(++˺-y"$&kfU$TT+Gz,.*p!Έۺz~lS$+};QcA7nWӏ݊ӏ݊ӏ݊ӏ݊ӏ݊a }Sm=A(ħqG#Ǯ*-)Wzq Wzq Wzq Wzq WyKr WMt?2kvfE-eJ}^|4O:֞}w`j;_fp6✯n_PF6EņD:QF,z 'Wbv*%a1Vh)tI)Z -)E1Vb[]v*q0&riLU7o,Q4&ᠼfO+@xg-@@ J7< ^ew4 I߄rr$X^GCjKCp}ryw."yMKz\}oYkΫ)ޏ2hMWjh>vȣ+wn@g-ůŰYb?{tz>6o\{|z~o<6&+eARJJ<>3g}ǣ$@HZ΋k#xg~;GWS\\TTӖ5EkO-$3 MVqiAWb_v*U1WAv*UتEd^'|h269FKU\ < ~;{A&qfI(H!zb@Ds!=0yB` Ṇ+ie 0tu= >#>@ˊxa8 wN !W+b$`hTST_fpPyJ$CEY u=S?cՋkv+EKQAvjI?{npR Kê) 1ї++ nԮ*኷v*UqssJb5?$?/)˪H#SxWgE̟(/.~3¼>ǒj?shX~֥E v.O{aqG?dG)~C<R.IVNG|8/_g.Gտӏ=c8~_o>phwNZ~􅬮M5njkLw-l0L$y m~  r0v,7<5 gAB9?6-?LpDUo*JI&܆{"LoST;= q ^gdG1/tFZ?yWxߋ#tϚjv5ӏbGu4֣Mr>\!;O6E7C4=o<-bJrVR z3rKA&l& q㑉a'TЪGr'tܖ9ǖׇw0A;;QԏD>gL%4x 3FB| -/h#=:G!Pj39UثWb1桡^\E$RsLW|ͫyZ5.ZI<‹^gϺdgy=lY2=Xb5;v*UثWb[4#_{ռKuӚ}1b,vHHT.{Z?}$Ayշ]dH޹on'2_a?G rO mUaH3TdJ;̓^<@=˘~}ҵ7XK>iï!M:0qgi88\RFa9"%=Bn=7ٻv*X@~-`yP|[I&ʤ'`7۱)O9O ~E))_'OȺ/?SK/ԾO柑u?_cRY~24aIA;U?Kdig?!yװ[XZ4PHK}0+v-Nm{7}nCqǬ+9rT;0C>d|\Cݙ䑩Y؟nZ-4c_1b"9 W3)UaFR-GAFVMGq7rl|]8AiC\HyOoId& +:gZvӠs7ev\#@z =<'{}QOrOu_| c4KEsZT+ (M;>k.~D1c|O8'hv6D}q8RU2SDM4:]2:_g}>ǣb: qCښwt?{ϕ9m1y2(` |dwOH)^.Zlk?HK=8g{QQQR +yה:8N3MȎEXG =JV@튾S䕮$e%5*i;7Pq{@UqUq;AV[Y^*7⫇z?^*qI*%JmuS_RhZ,Zl(h1VMv*I WvwSx'lu$I`{b0 y.m hdGJwLqA؃>'Go" 9ń6A7G e4u8N:9 r}G;Dj7H VܛKkm5e6*h A`t"P$\w;X=6|$8$cw]B')`U<ɭyvs>|ޣ܀JyTANBF/j= 48u?T>H?u:#P7>e}6K)m\)/k+T"sCy&vsc1&_X9lep3^u =JP[N*m3N&WV?? UߢOw4vOonb*~Giʟ*l4Sۦ* t F*]v*U@ܚb&vMw4PC yYQ|Yg1e#@s%,c󿜴Hiڋ_PJ?CG~#3ǽ'fg-NQ9. => =_Gǯm.wPDz j;a~de&= =87/7vY+-̺b'ߕ[]Rh"^E{W;f=_hdc^c|cjuy~߂Gkr#yl4k O\W?_b\Hz" \G}jR˼>fUzv=U_ϨQX늿?=?4a&yO$i`׬ITk0aTJG v4{wh281Ϧ>^go}gi'",?/{ vU򓜿;7_Nc7pZB}k/,fowB|k/X>G?'>4Ask_7t~G3G_'97/nYCW='4?_ݏ_7p__`G)_pSQ? c;COR+~ש[|yS/Gy &[pM zU1JOYnZ7ooȷum~\M.Wo#4N; MRX^H}w8G$Dl`} #ɥث\Us[#3Tԓ Uh߱2[h5kR}:O89_ 3nLOo#!!vZm%9_Ϙu~[U{+aAt~@$r5jlX~&9pbSos?'~@<hvާ[Ga~)6qث'|8]bcA[}>/\Czh΋e;Kz/)gI׌k(#웏#>S9{@c(XvsaRwߎOL㹽4Id31ܒOr{ Qc@P[a ӶM/jETP8 7O{FE!)_-}-S^3=ҳܻ#>IVo{;7BeLv*UثWb_?(|k~V+cpG˟:{g{'νFǬoP~OtNr{Ƞe|Km8Z  '=;0\}?d=p?77V%ni[Hܿ?Ow_^7? 4k%*KEArϚkv>/zb}YqwzLs<лIu1h[7֡&1Fw>mݱ`ICRb<VGU>Q$9<[Qg%k&9*ui=өڨN}4~ݫ?\8؀#;8BX;GX`g{bRYH=E>skrd!3=VYq@?"  k\(ToپTS_|+cѼ?[ VVۭIc"(="#@lAl󭇖k.vBBa;vo;I-^\0Gb:@f=&3!> ~x|d{eQ6݈FSW٥g;X[ idhM\q#Xvy)6$۰*_ng%{gڞf :==7Aڞ0i&Ir`;43F{-iiCX!<Oǹ0oc'ҙ>RӮhwd?W1Ƴ+|=Ʃ}7R勵AV&va>vfK8:DW3`qO7c6P f+@xb"Hh1ULUثWͨ^żYa-jX^]s ;oN*⭏?X_* N%[f*~@ğ#\? bO-!cC˿gqW`Lj튾Bκu2Ei,03@wNI~l=-q 3xlc3H&Wc{[ynnbyMs3qfb˰ij2 xg9lA$ 7,Y Eslwn^m ~|Gg)=^7jK}xw2Tw]t"wqT0u1EA /hGG/9H}4,:X∏}}}o;->8 (Q훷)-:4 *"8@UqWb]@zLQ>UJ?(bA]][\1T[g"UGvA<}C ؐA؍ٯ^vzmTQ##pw :>=D<^ą rk!?&,|㟊:j&^?yc~;v{:y4^Oy8hloDPiޕ'=Kc/!ã##g9{w!Qz fibF_>mBfVgL羟мaƁ`U+튳m1TF*UثWb]v*4b4ԾHKx/,=2  δWf=˫8uu{;u\,lUA9g==i>O-/?-~w3MÊv{_gJu0v*v*pJ!*;:ͽj{/#30_{%3oGы^.5u?}"5 5$ *UثWb]Aኻv*UثWyZ7G|_z`o}$K_wu y΋)X>db]v*uğUI({B!u{{{U_! vƞ ȼm#O&'k#5etP[&vzg;?&> >> endobj 302 0 obj << /D [298 0 R /XYZ 72 702 null] >> endobj 303 0 obj << /D [298 0 R /XYZ 72 680.3998 null] >> endobj 300 0 obj << /Font << /F19 306 0 R /F15 309 0 R /F20 313 0 R /F31 314 0 R >> /XObject << /Im1 299 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 318 0 obj << /Length 1767 /Filter /FlateDecode >> stream xY]o6}pdfE}sɚi. jd˓IKRdZWEئyx.//%3?€x0Eߋ$pn-F*>0]:a#F{>jKzþ; ”Q y.=}0[W9X}3n,] (6+(z?Q >ӽW5S'8lwXz|Ч<4v hr< #<oUOQ ,"_x\QW=5p?~[P,y{.ɹv4ɡyMVL6߉dk(&Y?~YkIg C~]]0rS7Yeɘ?O %^.E9tò:a,sGs|1S9q}JE\n)/}!c!bM?fTT9- s8X.as GM~){ 3غRl-; ~Qv_(nLGsU&⦬slA;7]maY+ *~5f͛G@ (ETflG#2 z"){j&\~u{;qmcz啼1 NK0jѮ F~ٗE5 'Ꝫj4Y{ r…U:$q{r%8 Tc~Gb/鳞TežӽHGPj4 MDMʶu#5ʗUNel=5I$8WllR?dQ+U8?`%1;pcQoaS­#Ve&4Yy2I aQ&Y&%;C:+(*wItsf0tMMv#u֛ǭ5lz9Oqlx$ns@& u#5 8 =|~Ҷb(EaP llau Z(1fTu|rbs]EchS_}СJvG͈04` e5C&̰jf YYs9gXQGE{Fh( 7aT3b:fzMAzܱXɔ|t`Fإ!H:YߪA.*xγSp=MF6#lagĐuU2\8[ n|J bIOo={fpcb~>„7C.aK7C`/ύ0Ӏ~7^uy(_b6p@C,#aaI{Ǧ(d0|$e_FXendstream endobj 317 0 obj << /Type /Page /Contents 318 0 R /Resources 316 0 R /MediaBox [0 0 612 792] /Parent 315 0 R >> endobj 6 0 obj << /D [317 0 R /XYZ 72 658.6379 null] >> endobj 316 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F32 324 0 R /F31 314 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 333 0 obj << /Length 1055 /Filter /FlateDecode >> stream xڵW]F}ϯ[LZ"X* '&6}vlXvwf|='(Pm AˋkH ߈#"| X;Qc0Jؤ_77BAH+_c c-q٨?y+h%\#Ż4JjArFB wEԶ05iDHZ;"%uϳR.W¨MlSPa(*Q6&NxW3,~*,~zt9d$'@Dxj}+U/rϴ0v 69Hl1A1?_ߐU@œIPqiWR [ҁ.dPAu'c-d~[tHCua9rP٬o:s }*kT2-|!tFK wTOMrm)pTI< 6K+b*yR@4?RH&:Eѓ>EMLKNU8wj9Ɲ02|z:?cD|?q ЏZ}vi aR+lv׸i7^P8wK{5Nɍ3ujQ6jx Fqbj=7 H26S֘!A-A4HpBSeg(5Bgeoq?Z||*[11$6>% pxhơmqa6 + CdpcY<SrN,'O%lHa$`-4L8 1os)#NZuY[wʈZf ĤY(ܓA:>~D2IS#?J5FX(7pDZ8'ӆvIᷜdpqKFu +nRfzc P6DO/]endstream endobj 332 0 obj << /Type /Page /Contents 333 0 R /Resources 331 0 R /MediaBox [0 0 612 792] /Parent 315 0 R /Annots [ 335 0 R 336 0 R 337 0 R 338 0 R 339 0 R 340 0 R 341 0 R 342 0 R 343 0 R ] >> endobj 335 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 620.6155 248.2505 633.5171] /Subtype/Link/A<> >> endobj 336 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 586.3167 264.0688 599.2183] /Subtype/Link/A<> >> endobj 337 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 552.0179 270.3718 564.9195] /Subtype/Link/A<> >> endobj 338 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 517.719 299.493 530.6206] /Subtype/Link/A<> >> endobj 339 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 483.4202 310.4324 496.3218] /Subtype/Link/A<> >> endobj 340 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 449.1214 311.5839 462.023] /Subtype/Link/A<> >> endobj 341 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 414.8226 267.9475 427.7242] /Subtype/Link/A<> >> endobj 342 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 380.5238 254.9172 393.4254] /Subtype/Link/A<> >> endobj 343 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [99.8033 346.2249 281.5839 359.1265] /Subtype/Link/A<> >> endobj 334 0 obj << /D [332 0 R /XYZ 72 702 null] >> endobj 10 0 obj << /D [332 0 R /XYZ 72 658.6379 null] >> endobj 331 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F32 324 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 346 0 obj << /Length 1539 /Filter /FlateDecode >> stream xr6z 1%IXA+ / ݄p kHmsAO*FaƂ$IW0WzQ\}+.ZwqVkbcFUЊ#i%)Ҋam%Nq]Qy'+/d6=h5ְbvvf_o>lt#^g&fkRi8" aX_oVaF*EM^_17|BoJJeF*jE cVʭ*#e( >sW>ou3 Jh3arwðJv5S”t$ D(#3 hVp=@ T:rzrD?YDVTc3he6Cꬄs@!B`[4VVͺl Ҽ#-$AGEqr0dk+ ׆j4.job(юxJV9Zľ-$ʲ/uaRכ| ?RwA9j)ajmi%>nҧU\w(nw#V9U}hXK T21{37%78>Z8VʎcZ4nTIɆ"}߳}=9Qrq' eq%U4z3ׄͿ񿅿V`C…Z*RPΑW2p_C[(F˱p# ~B+^U(Sro-r*G5{Zx;PF/ɩ$wI$<dƈR,w"؛ҳ<4\^!-~q2[e,<.;qo.&>0TB#(V9=ʡ#ʣ(xܝGٌxP0A7CG0?=4˦>Y͛zVZݎ V9u Cy$r2[3 1P93Czi3CO׷jc|v4fX$+B# V9a[CeGp*s~6p!cn"pg3^n uewƺ"Y}G[d$G#:=qwz9\s E 79;3{E,a1Q= ^׻Kxjw =OzJ*Ƿ#DM~%}Y)05&[h/dP;I$4A;Dr 3I{MJN Ju> endobj 349 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 450.7785 177.0267 460.3468] /Subtype /Link /A << /S /GoTo /D (section*.1) >> >> endobj 350 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 430.0289 155.9357 439.5972] /Subtype /Link /A << /S /GoTo /D (section*.2) >> >> endobj 351 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 398.3702 185.0866 407.9384] /Subtype /Link /A << /S /GoTo /D (chapter.1) >> >> endobj 352 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 366.7114 151.6868 376.2797] /Subtype /Link /A << /S /GoTo /D (chapter.2) >> >> endobj 353 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 343.8406 179.6025 355.5301] /Subtype /Link /A << /S /GoTo /D (section*.7) >> >> endobj 354 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 325.2122 178.8449 334.7804] /Subtype /Link /A << /S /GoTo /D (section*.10) >> >> endobj 355 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 293.5534 180.5881 303.1217] /Subtype /Link /A << /S /GoTo /D (chapter.3) >> >> endobj 356 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 272.8038 173.3297 282.3721] /Subtype /Link /A << /S /GoTo /D (section*.11) >> >> endobj 357 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 252.0542 147.6024 261.5012] /Subtype /Link /A << /S /GoTo /D (section*.13) >> >> endobj 358 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 229.1833 205.4813 240.8728] /Subtype /Link /A << /S /GoTo /D (section*.17) >> >> endobj 359 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 208.4337 207.057 220.1232] /Subtype /Link /A << /S /GoTo /D (section*.20) >> >> endobj 360 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 189.8053 186.5419 199.3736] /Subtype /Link /A << /S /GoTo /D (section*.21) >> >> endobj 361 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 166.9345 184.3903 178.6239] /Subtype /Link /A << /S /GoTo /D (section*.22) >> >> endobj 362 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 146.1848 166.8751 157.8743] /Subtype /Link /A << /S /GoTo /D (section*.25) >> >> endobj 363 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 127.5564 119.0873 137.0035] /Subtype /Link /A << /S /GoTo /D (section*.26) >> >> endobj 347 0 obj << /D [345 0 R /XYZ 72 702 null] >> endobj 348 0 obj << /D [345 0 R /XYZ 72 472.5244 null] >> endobj 344 0 obj << /Font << /F19 306 0 R /F15 309 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 366 0 obj << /Length 2112 /Filter /FlateDecode >> stream x[M7WQV4? k $\dl hd~{&3|Xlc03R׬"f ʛ6ȿg=CI6#?r-P݃xT(qԱf6xi,X}═1iVk6(#DJjG8zO 6qݏO`DRo|?D9cOkgR~zso'D)"eķpCRR7rxrt\|=~m?=c&N&6Q5"Cf,4zhne|eFqqD82I(){i)H堤漤MV%QubUHI! j9^Cuq LVDQ&p&IAo0]Y,,m{8f b;ČeUs߯ O& gE}\^/<`%%Ð"\ޟv;_<5#+ƾCW@5&tqCXr, ~QpSs^[(bQ5w0d:Zґ'#bәE SFr"/-y9n9$Gv"Wj"`t87uYJ N8NSw7f4QR!IܥhD.G#5Eͳ.yAi,mF0/_VA-?l:"Uwuou]Fr4Rs^"ǫcA%1̩G 5>nyU|ƏaߵaLӂFnb|Cոc4WRS@|e!0wSϘ!wo )PԿov,!wI漆%J\q"c G 5K(aT;utt<Ǔp2gvi עjT)|b_Xj./bKoPe:u0dS]n";TeOc\)|Kyg'E7(昣j^+z2=B ȼ][fdޭU2xde^ Ee^xd_dȼ!ӷP% í 2Je5~k:/E1y993Eй0)5(',X9Ưj޿9rNm4V5\TKs17)-4W{vNO5; E2NY+l1L[v>endstream endobj 365 0 obj << /Type /Page /Contents 366 0 R /Resources 364 0 R /MediaBox [0 0 612 792] /Parent 315 0 R /Annots [ 368 0 R 369 0 R 370 0 R 371 0 R 372 0 R 373 0 R 374 0 R 375 0 R 376 0 R 377 0 R 378 0 R 379 0 R 380 0 R 381 0 R 382 0 R 383 0 R 384 0 R 385 0 R 386 0 R 387 0 R 388 0 R 389 0 R 390 0 R 391 0 R 392 0 R ] >> endobj 368 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 668.4446 140.8899 678.0129] /Subtype /Link /A << /S /GoTo /D (chapter.4) >> >> endobj 369 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 645.5738 163.0267 657.2633] /Subtype /Link /A << /S /GoTo /D (section*.28) >> >> endobj 370 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 626.9454 136.9963 635.9682] /Subtype /Link /A << /S /GoTo /D (section*.29) >> >> endobj 371 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 604.0745 144.8448 615.764] /Subtype /Link /A << /S /GoTo /D (section*.30) >> >> endobj 372 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 585.4461 159.5721 595.0144] /Subtype /Link /A << /S /GoTo /D (section*.31) >> >> endobj 373 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 551.6661 248.0604 563.3556] /Subtype /Link /A << /S /GoTo /D (chapter.5) >> >> endobj 374 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 530.9165 161.2691 542.316] /Subtype /Link /A << /S /GoTo /D (section*.32) >> >> endobj 375 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 509.5608 162.5419 522.4624] /Subtype /Link /A << /S /GoTo /D (section*.33) >> >> endobj 376 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 491.5385 130.9661 501.1068] /Subtype /Link /A << /S /GoTo /D (section*.34) >> >> endobj 377 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 468.6676 160.3903 480.3571] /Subtype /Link /A << /S /GoTo /D (section*.35) >> >> endobj 378 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 437.0089 126.4976 448.6075] /Subtype /Link /A << /S /GoTo /D (chapter.6) >> >> endobj 379 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 418.3805 142.1176 427.9488] /Subtype /Link /A << /S /GoTo /D (section*.36) >> >> endobj 380 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 395.5096 207.4207 407.1991] /Subtype /Link /A << /S /GoTo /D (section*.37) >> >> endobj 381 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 374.76 121.4812 386.4495] /Subtype /Link /A << /S /GoTo /D (section*.38) >> >> endobj 382 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 354.0104 172.9358 365.4098] /Subtype /Link /A << /S /GoTo /D (section*.39) >> >> endobj 383 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 333.2608 170.4509 344.6602] /Subtype /Link /A << /S /GoTo /D (section*.40) >> >> endobj 384 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 301.602 233.0968 313.2915] /Subtype /Link /A << /S /GoTo /D (chapter.7) >> >> endobj 385 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 282.9736 108.2084 291.9964] /Subtype /Link /A << /S /GoTo /D (section*.41) >> >> endobj 386 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 251.3148 192.5729 260.8831] /Subtype /Link /A << /S /GoTo /D (chapter.8) >> >> endobj 387 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 227.838 125.4812 240.7396] /Subtype /Link /A << /S /GoTo /D (section*.42) >> >> endobj 388 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 209.8156 114.2085 219.3839] /Subtype /Link /A << /S /GoTo /D (section*.43) >> >> endobj 389 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 189.066 111.4812 198.6342] /Subtype /Link /A << /S /GoTo /D (section*.44) >> >> endobj 390 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 168.3163 102.4206 177.8846] /Subtype /Link /A << /S /GoTo /D (section*.45) >> >> endobj 391 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 144.8395 168.4812 157.7411] /Subtype /Link /A << /S /GoTo /D (section*.46) >> >> endobj 392 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 115.908 142.2778 125.4762] /Subtype /Link /A << /S /GoTo /D (chapter.9) >> >> endobj 367 0 obj << /D [365 0 R /XYZ 72 702 null] >> endobj 364 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 395 0 obj << /Length 2337 /Filter /FlateDecode >> stream x\K6Wf8duRIv%-IUdIh6Si$ 0VRS&F7T#´pzFop\! 'N~pKTXzV/""lH V_.~^}W dZ?-bjh4 5]lA=4*V| 7WoV﮵ cُ?j |;H'5T3.unnS.HAIV-EBXe'9C:U-% xyr{?v}߄R)Q% ?!b)0'wOV{7A 0yyTo87!#5v)n ICX-ZY2 oQ%C- xo8Gp$xN5  Nd-Zz-d~=ISkBM1[T 1}&wι(wE smd@ql[ # dk%xf#N||}[88_ HݙGL0>\p7XDT(cAxe&x%f۞㟰0̓CowpDㆵw[*K-Ρ&=;]:gZTg5P Ҭ4yZ{/j~pSܧU5Ƿ䦰mh*'U(o4 }7H7bs&Ib4Ale|<7=#k8\o,Lۡ_6?1ai(y݂ Ð 08}4~$̑&IQ7 I¬a:-]qܽE;HX6sF8LjPY<-Xu`M![Vym.ݥR6%B}1B5oCArF'`g~tbq"Ϝ1J bJA[uw/~M[IݪӋTʸ2KS}~͹!u 8GmV P(RYKۏ !%ʮm5aP@PYT2H0oD3u' N S:LJh 5PvLU27=Cj)\ 17vpe.[XYىgBlO٠"Y*dN7oLA;μsQyu8¼E FXҼavz:]~즫]B#ʩBEuUǯ }tuJSbqZ " b>0p?6y0 a5W$w=$ d׳r"y9?g?s~cq>4g)&E]^̯ ](;+TDrn@cX3ԜHG"a:㌺1h պ&Mf ගw5tl︞|Y7͎Ӱ5Un鈴N.F HZmQWS1H`,$8F! ڣ[[߁kvVv:^NuKpӲ M5A?uY7eKވYoczqǾN{>ԑ$^lA _l Cn9%!pXFv5o-P8y Bq] Fz}\P3\5b[*od $` jendstream endobj 394 0 obj << /Type /Page /Contents 395 0 R /Resources 393 0 R /MediaBox [0 0 612 792] /Parent 315 0 R /Annots [ 397 0 R 398 0 R 399 0 R 400 0 R 401 0 R 402 0 R 403 0 R 404 0 R 405 0 R 406 0 R 407 0 R 408 0 R 409 0 R 410 0 R 411 0 R 412 0 R 413 0 R 414 0 R 415 0 R 416 0 R 417 0 R 418 0 R 419 0 R 420 0 R 421 0 R 422 0 R ] >> endobj 397 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 666.3234 123.3297 677.7229] /Subtype /Link /A << /S /GoTo /D (section*.47) >> >> endobj 398 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 645.5738 120.2691 657.2633] /Subtype /Link /A << /S /GoTo /D (section*.48) >> >> endobj 399 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 624.8241 143.6327 636.5136] /Subtype /Link /A << /S /GoTo /D (section*.49) >> >> endobj 400 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 593.1654 224.6333 604.8549] /Subtype /Link /A << /S /GoTo /D (chapter.10) >> >> endobj 401 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 571.8097 209.9055 584.7113] /Subtype /Link /A << /S /GoTo /D (section*.50) >> >> endobj 402 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 551.6661 171.2085 563.3556] /Subtype /Link /A << /S /GoTo /D (section*.51) >> >> endobj 403 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 530.3105 186.9964 543.2121] /Subtype /Link /A << /S /GoTo /D (section*.52) >> >> endobj 404 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 512.2881 216.754 521.8564] /Subtype /Link /A << /S /GoTo /D (section*.53) >> >> endobj 405 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 478.5081 185.5714 490.1976] /Subtype /Link /A << /S /GoTo /D (chapter.11) >> >> endobj 406 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 459.8797 176.057 469.448] /Subtype /Link /A << /S /GoTo /D (section*.54) >> >> endobj 407 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 436.4028 305.5724 449.3044] /Subtype /Link /A << /S /GoTo /D (section*.55) >> >> endobj 408 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 416.2593 176.36 427.9488] /Subtype /Link /A << /S /GoTo /D (section*.56) >> >> endobj 409 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 395.5096 161.7843 407.1991] /Subtype /Link /A << /S /GoTo /D (section*.57) >> >> endobj 410 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 365.9721 126.0733 375.4495] /Subtype /Link /A << /S /GoTo /D (chapter.12) >> >> endobj 411 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 343.1013 155.754 354.7908] /Subtype /Link /A << /S /GoTo /D (section*.61) >> >> endobj 412 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 324.4728 104.5721 333.4957] /Subtype /Link /A << /S /GoTo /D (section*.62) >> >> endobj 413 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 303.7232 148.663 313.1703] /Subtype /Link /A << /S /GoTo /D (section*.63) >> >> endobj 414 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 282.9736 144.8751 292.4206] /Subtype /Link /A << /S /GoTo /D (section*.64) >> >> endobj 415 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 260.1028 198.2994 271.5022] /Subtype /Link /A << /S /GoTo /D (section*.65) >> >> endobj 416 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 228.444 131.4369 240.1335] /Subtype /Link /A << /S /GoTo /D (chapter.13) >> >> endobj 417 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 209.8156 148.1782 219.3839] /Subtype /Link /A << /S /GoTo /D (section*.66) >> >> endobj 418 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 189.066 159.2388 198.6342] /Subtype /Link /A << /S /GoTo /D (section*.67) >> >> endobj 419 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 166.1951 189.1479 177.8846] /Subtype /Link /A << /S /GoTo /D (section*.68) >> >> endobj 420 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 145.4455 157.9964 157.135] /Subtype /Link /A << /S /GoTo /D (section*.69) >> >> endobj 421 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 124.0898 266.845 136.9914] /Subtype /Link /A << /S /GoTo /D (section*.70) >> >> endobj 422 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 106.0675 173.2994 115.6357] /Subtype /Link /A << /S /GoTo /D (section*.71) >> >> endobj 396 0 obj << /D [394 0 R /XYZ 72 702 null] >> endobj 393 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 425 0 obj << /Length 945 /Filter /FlateDecode >> stream xWM6W(C A4mi%A]+kkzw0eR7@ c8|||f %˅d7D[y@;"j׌q5!B a,N<@p/;v{K8@0_VY2%1HP\1vsִItF?f)ˆ P PWMG{ =V: ZIOh=jĶvjȘ2#DO{?cg@QKÑntFOn/pvzPKn`Ĵ"n˺:_s򠁃 %"[<3ocm=wDh.ZNzns[_`ks.ٺӫO+Ҳ;t?W۱MOxE-8y:OQ# 6[Lvx˥BA@c6aDޖp*}])>>vUtaߕuC/FP5ï +^`G;QK[167DhVjxѤ Jvigm(?YސRۺh.NQn0(uPKO̝ ^o~dѤ u m$`SԛF2%M~%͊*e-|? ZG2%'b^N5>Nh:DP)oTy_ދr_mOPO9r|gy,GDILͻLsKXPh?Qަf3Ӯf Ú-dafۭۖ)pkU[ͧÀwZo Yåׄ`mK XΙzGLh'THsendstream endobj 424 0 obj << /Type /Page /Contents 425 0 R /Resources 423 0 R /MediaBox [0 0 612 792] /Parent 434 0 R /Annots [ 427 0 R 428 0 R 429 0 R 430 0 R 431 0 R 432 0 R 433 0 R ] >> endobj 427 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 665.7174 207.9662 678.619] /Subtype /Link /A << /S /GoTo /D (section*.72) >> >> endobj 428 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 647.695 142.1176 657.2633] /Subtype /Link /A << /S /GoTo /D (section*.73) >> >> endobj 429 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [87.3674 624.8241 146.9661 636.5136] /Subtype /Link /A << /S /GoTo /D (section*.74) >> >> endobj 430 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 593.1654 316.1539 604.8549] /Subtype /Link /A << /S /GoTo /D (chapter.14) >> >> endobj 431 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 561.5067 290.0874 573.1961] /Subtype /Link /A << /S /GoTo /D (chapter.15) >> >> endobj 432 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 531.9691 219.2773 541.5374] /Subtype /Link /A << /S /GoTo /D (chapter.16) >> >> endobj 433 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[1 0 0] /Rect [71.0037 500.3104 179.3912 509.8787] /Subtype /Link /A << /S /GoTo /D (chapter.17) >> >> endobj 426 0 obj << /D [424 0 R /XYZ 72 702 null] >> endobj 423 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 437 0 obj << /Length 270 /Filter /FlateDecode >> stream xmQMk0 WIܺBnrvcIO $!ha{R{,OKg R/FP@SDRr:[yYߧ;kȴM깺6I,:8'AAg S7d$ =`d jH,< ;`Hqr##m*-Jk1l&!7&l_G=eч VsK}hapO0hGC#20nendstream endobj 436 0 obj << /Type /Page /Contents 437 0 R /Resources 435 0 R /MediaBox [0 0 612 792] /Parent 434 0 R >> endobj 438 0 obj << /D [436 0 R /XYZ 72 702 null] >> endobj 435 0 obj << /Font << /F32 324 0 R /F15 309 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 441 0 obj << /Length 1593 /Filter /FlateDecode >> stream xڅW[sF~ׯh཰,u6NZ3L"a }e!9gϞ˷2U*X7 lB$f#2"wg<6XݣHcD,V7^z :0ylɈUF F,׫Q&ֹ'ydt k@yLЕxj܌LTgULI, "'Gyj=yUǙ5)G9JrL$#v2T$+8CF>~lwHR  Bsz@zD)k/ Ƥ*δ5.(-XyBa9ϐjyꏂ .%Ysa;>ribV'@~@㵦$iE?UQ$dvψm ) JnǮ5FWߺC>z'@v%e2aM!5 S&%jnɥ+SAXa=bq9(>slcC ˚dl7Ϗc8miQۂ=rBI]G[)i4 q??Ń0yvG'`-VKע:=Ma0 Ry:޳3u jjeBsZ9Q̶sJQS!_;u -qDIv9.>3%&𤔳MQެg͗,7_Coy: RR^(h3 t3#wJ={j@ypݒne(j'WxV9:UqƟ^4endstream endobj 440 0 obj << /Type /Page /Contents 441 0 R /Resources 439 0 R /MediaBox [0 0 612 792] /Parent 434 0 R >> endobj 442 0 obj << /D [440 0 R /XYZ 72 680.3998 null] >> endobj 14 0 obj << /D [440 0 R /XYZ 72 680.3998 null] >> endobj 452 0 obj << /D [440 0 R /XYZ 72 178.2706 null] >> endobj 439 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F33 327 0 R /F15 309 0 R /F51 451 0 R /F31 314 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 455 0 obj << /Length 854 /Filter /FlateDecode >> stream x}UKo0 Whe:: {&c 3Y?Rh!@LQG#%Oą .e͇Hkƍ.iP8]Yf]ߊ<YnEXS`X'o҇F%ӥo"z8)Kf-H/S&(uJkd/اJ&wO٘f"ie:"4_W]Yn2~gҖ6"mi~Dߎ8 5b ͔62jeZs+gƔ\i |uUzp(sY~܀tB+C&\XBy"DTnX(P9j=x=}sh,@)+ 1yX#Zw>]\_ bn%JCE2j B\[陨MW%YT <j= ;ק -7Wi /dv ~v؍gPzujSJÐ:.ط ˙TSs,ϖBPH[)z B-%Klki ʻxjc!pL>@cNiAOG䪺0|HS_:C"9TMR δx"-[/Qw& m 9 'nĊfG80gZZ:*u<@W_o!i^>lf,οjSanmaAK6om 7B i ޼HJVgG3w5k5E0\!:PV lbQ Ld*endstream endobj 454 0 obj << /Type /Page /Contents 455 0 R /Resources 453 0 R /MediaBox [0 0 612 792] /Parent 434 0 R >> endobj 456 0 obj << /D [454 0 R /XYZ 72 655.8483 null] >> endobj 453 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 459 0 obj << /Length 1589 /Filter /FlateDecode >> stream xڅWYs6~ׯ& GߒL:iL:`5E${a#`^, IAA[=Pn;QY3Vq[Vu$R*σBjLe| _͇[`.EXc`1Eś$)ɵΏxN I)Dewӭ0P-QSN2%DQZȋ+*Yr,xU)敊bT佤 R nhG vBە -+u:mvB"8(7)k9Xvcod>R \GO2#ֲ!{@X7Cǫ=ED:7,1?]f]e,4u#([DOw]3%C8`_Vc. :oNz Z{p^J(kvHGAuD1\m3 w7nXRqa,`։"tl~BD "v +-tT]d(W2[32-KZSbYFvi:ZZ-:x0Nθjyp6s/ s[u*0RʦzHXv̀+ju:O*TY %Cq1S:6N[8p[T%qsv9H i -5OhBNvN31:stLjBGl$?]_Ц+HAP9nǮvld)mF3#.I ?s.2\F0IERt􍅖KndP$BId4׵轖e>|=( 64Yb?GB3Y[ @"@na䗏z=$4QNcVq(zTqqbkTjjRrDqǑgV0a)D)׼W~t\sGW!zgq=< #gBΞ)F7V8CDs w.V{n=vJ_E4;N)\6L:1qƍC 7_YChI9Wq/| 0FP?D\[$o'+ q$?UG5|Nr-ȳucl 13I5CsT7ax9pN!,YOYyIfq%endstream endobj 458 0 obj << /Type /Page /Contents 459 0 R /Resources 457 0 R /MediaBox [0 0 612 792] /Parent 434 0 R /Annots [ 460 0 R ] >> endobj 460 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [75.2462 263.8117 251.5723 276.7133] /Subtype/Link/A<> >> endobj 18 0 obj << /D [458 0 R /XYZ 72 680.3998 null] >> endobj 22 0 obj << /D [458 0 R /XYZ 72 198.8209 null] >> endobj 457 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 464 0 obj << /Length 1755 /Filter /FlateDecode >> stream xYo6_60T`aa_mmXJlT\}qk + z=.h Wmݔgj/\@P0P KU*Hg5Kq@5H53ֱcE4ѣaxUmKmEOVa -<-}7-@-*нw9Rb2h]=`nhGpY*,/氦Fs۪Q0b]ge(NċHf5Hx1E^~}TŏNΊspThJ<1L>JfJ+@dGb1!uup{&D{j$cbeeه1ЄaIbi^.vϰ-rÁw쾹#!YXv"9$# :aH>י`\F3|6t,v?!o 4'85zՌЃ̉LOZz1@V4=% PoڂyTjBe۬lhCm!Ҹ\t,ա&.q@rendstream endobj 463 0 obj << /Type /Page /Contents 464 0 R /Resources 462 0 R /MediaBox [0 0 612 792] /Parent 434 0 R >> endobj 465 0 obj << /D [463 0 R /XYZ 72 662.3954 null] >> endobj 466 0 obj << /D [463 0 R /XYZ 72 230.5956 null] >> endobj 462 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F42 469 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 473 0 obj << /Length 771 /Filter /FlateDecode >> stream xڥUKo0 W2fVWGnء]nmA.jQ:[(Ĥ"O ?N ' )~ʷҒ6$]>jQ;iO @ AK^3Mm8fD|`lS7z:GVX0z3N~1戀@ R)n9YbV;eZ*.q!9͵2FxO"څ(v'3%,x#qqx:DR`t*vrP)W>VX.Zr\ZS9FAy#,cq7hRY?[ Vv4`V,O6^_.1Xl2ab;mb Fh)mC)] C6$ "~FLua1Z*nRZi$jĝG'Tv@NLuM[Z*#>j,F{wtoڲ:UTG)o,'\7 Ez2C"c"835~FkoN3LHvk4o ܈ki&1M%/bd4pc!f`Ħ:R;}3Vhq(ׁ2eݝQNiۜ$Sa|I³K`C`2nXy'E!I'qOu p96aڀ36X단-?<>f<3$5Z/endstream endobj 472 0 obj << /Type /Page /Contents 473 0 R /Resources 471 0 R /MediaBox [0 0 612 792] /Parent 474 0 R >> endobj 461 0 obj << /Type /XObject /Subtype /Image /Width 379 /Height 237 /BitsPerComponent 8 /Length 33141 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream JFIFHH Photoshop 3.08BIM ResolutionHH8BIM FX Global Lighting Anglex8BIMFX Global Altitude8BIM Print Flags 8BIM Copyright Flag8BIM'Japanese Print Flags 8BIMColor Halftone SettingsH/fflff/ff2Z5-8BIMColor Transfer Settingsp8BIMGuides@@8BIM URL overrides8BIMSlicesm{start2{8BIMICC Untagged Flag8BIMLayer ID Generator Base8BIM New Windows ThumbnailpFP[JFIFHHAdobed            Fp"?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?'1|ޅUV9sfC?T*cX׷~s;}>K6)MTI 7vH{G:I)Hn١vQwh,pi jD\t a +.|P%IBCh+S4HJQSzVS+R]]c_3]{-K-&M"_]c n=UC_]v nqa٨cmk?U-;'0ܐZcm^6*e]^rU鯞@G[p=a;qMG%#a<4K@=6Y6=9}wn|jKjikdɒIo'$:PsM":fZ٭mmXԊj1oaK!`KH"ԏ$'#67nvƛ]Ⱦ?8Uԙ] .#p'J S˜ p"dOu22d@LƤ8Dy>=JRNFSO|m`[mAmUgk[zN[[@msCKcL>lp⒗I66%2IG{|Gޟs|BJ]ep ˲5Ϯ9}64} ۖsqN=;65m@l{?y4ՋWFL/kXև]<PSӚ22Ӵ4mfw浨1oI M)!~z~XRYLOPHl0tR?A@λ*7clo~g"gP˘7> h3#;5Ju05VZ-۽V~mom~ϣb}W&o6nmAG3Ȉةn*]]9YPq&0S^mk1g\y9yXl2k oXk;NPyّs?o8Up-<|\ZUp󬸞nEY>us}*ÿY3[u kuVsOZ֨W 3n^÷zDs1҉%cd3FXɡﵣD4cC6h}6 hAkw/޺3 iO #Fu֚ĻavkwwQEqܦ3eanjݑ ( щ?Ot,p3WK_S׌49X,u'F1Z0 oa5OBZEhКSGv%Q4uCB\` d>ݟ?b)COG?Ig>?x_޼$pzS>TΒߥTq osl立I&l|GeW}lfݬv]GjEOZk+0C4uWCOExbI哔PQ`ZE@P^[&Wn_ww>?GbT`w߮=>Nc7O;߮k>ڷ=-rZ8BIM!Version compatibility infoUAdobe PhotoshopAdobe Photoshop 6.08BIM JPEG QualityAdobed@      {0  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?I7$T&q v?Lj'w?f_f`=;+o#ZiN@ۥEw­IB(h{Tm1W:'NpT3nImSb®]nqWWuqWWwUVw*a_?@MzOKJ ^lzZ} dD٘y~?Hf<^k-;I.GpRDh*qK\U⮮*m]]v*Uڻ v WcjUN/: U+ZG>T~~k 7V2>_>w Gnl#˧B"r7085ЇOe\B'?ee}~_7IиI[]br$-d)(-@j>&?wUYBQCzGBH٪v4'|OZsG,.LlXxĩvbxK\) }@* 1|g˯䵬/LAN(i'ρA< twuDJ}/خ%{E)#_L7!$W6~mŜVC! `~χ\{@>2^"CcP@mu.jD6񪇈oPW ARz7~w-O/n 6=A @r S߾;י}_{%=QַFbЋD2۔\es@H.+J8E|?a~6Sty$\$1k F1ŗ 6Lמi+*LKj^qH#A X+zSwlXI El(Yf+?w9ߑDY~WhKd֊o Ԕ(pe8G']v*4k_yO|{C(Y$T iԕ4n!S^'Z=rxO1t[gGNk)K 8V&ѵ\PRUUڷ\U⮮(nu]vv**UثV*qW:*KuYe cH*i]ፒb3Ìy~9mu"Լ:\Oo+1wŴb?FmOar~d_o>?!?xWpڻ_l.t;m>aŒ!bw9c)DGd1N1F|ZU[J1FVUثWb]v*UثWb]v*Uzh^$t=PwٟFB3TvYbT%2,w d$<پ s'K5"/tC94h7bTe<|"<]`4Y$E5#bVY%_kծ.K@Xg _Mjj}kjWIrZy[ӯHSmZZ9* H.$=X4|H{`SʤZĥ#fG5yK E7{Ekm%.*D+ HBmcіUD\ѩba+1yN_Iv_3/ZV fQ@8~;ЧoY Y dtTcQ$njST&14i!E,z*_I|v'BCDBɸ$ T|z,]~kAqV+1WWuqU_1W>bثWb[]v*UثWb]v*UثWb]$r9w 4'Ϯ^`ŸTXxLW !Ж!CYO]d[mϢF]]=|f[ca*w f޵$b\mmu1tW~`6:9 JmYP@ۉM\0olʓۆOUM?Riexۛ6'B)|Vv󢿨ܾԎ꼍[>b/56,7nEC,ApC^TZ;Kgo9-"gp(T>W DHER~ RkЊnkhn CUT$TmBVfÁį( vzᵦ* d 5G*/LDqH *w%'$ԓªWb]]O'e~C4wϖ=˓kwa! 4Bx;~9}˄.1g*)XU^~ OiUOwKxQ{:oZ[jWǿ=N~>{_^+Gs-95e4 XO/ai"TVKdZ{VRpQ'jήt9]^3~9yS7b]uG*UثWb]v*UثWbFi&vG;͔f-}ߤ;,ThQqPqJJi6„tj DUDPQb\m]\m[w,Uup[(nUUUWuqV늻*X\T//_a䯞qz~R=ryvrzGx9S7Jwi?'9H8=zxË=g~?"#W^e[yr o%%ߙDR|Iɑ~2o]r?ga8DV!o - /hP3rf#R/ߏڷ/dq"% 6v62P J>!7~<9~h"u5Y}+h0ؤLȷqʶnxqcR&$W"6;}~g1QԂI"Ǘu=cMu+ J;F(yCRT ;sB&\п㿸nwK.}B[cVX'9ZAԀDl*);}ޜTx⮨|U[5naqoeymzL25ữu}Ɩ~ƫakwki#F Cf~T8V5!)Rb.;?^x~lzO?l;.ۅWW W@̌Rݧ`/nJQ[.=>Qjkx_gd5Cwzqs}csfO0?zwn=6S.T(DޫfTSxpɖ$F&Uw3"\csF!gj :[!<< F JBE(2pj!fH ȋY7)JSN-x$?/O?=8ѦFqym#Eޗ*"A >[̆xu2$$dHY|U}xx|~=~k_Mh/f:ʯ2X]$BH<%)RL[^D.<ȞhQ=Y<ΐ4i˥fA\2m ?wˆw. 7k+I;oI_˕򍎛ewNek g?lVh}>Lk0^$5̒G2+0T.GAQjhJr;!Wm#\ ȕy'̲F7|xo'Wa+$NIMPBjb&*W *v&~}@ H!ֿ.mgͷ}7W/WTnt{hm8FQ{۩ bUd B5r12A~gu,Dv=ҐC/o뱸Rבno_y^=@mN^ꮺL> i,Uc7_r錣@r?DHU]CI%{-~bi,Vy2<'pTQp w۬E\d,oyWZ]v*UثWb\4BaN-KCE*qRӬ[k^8/5:13;Rmv,"25i-k9[ 6#t?b:ވjel)2K*Qr4n7\AF Kuquq.LU­nu†덫u-CWW: uq\RI_Q?VDrW_:O.t+ŮDvjQdxըҊUMW/E-Vxc2#B0AULRo1/r'qCuמ44EngLqLD"SxџaTQ=/hf R8PD'ɍqqJ|P▫ Gč?#Iy/r;qQB+ Ԇ 5IcZٟKW c!Mÿ$G)jB2@~(Pzʖ:֢0Dp0\ =&ii5'e3XzcPD}BB,yb1"?_ Ӽ\b]v*UثWb]v*UثWbky{QaNwYv.R~49.U=Cm,_c DJtzij$͏槜?IH>氶kgn &:qSJyýFk'J2O.qY6xD1<.Sjʼ$|k7:}eOpzbe+O/5F'mMm _F޿Y$#!`D@ p+jHK&{:QbW`C5ARJrc/m˾:3'?seK" GFMkzDݛ)]&S A)K y}̱M|QBWc6PZ_Yڥص䤳B^`G:bw{'vmƷqƣX!tsj:PRl 8< $\qwy~͔rx_5Eךu6y|t׮MR=ؼPnZxtdqgK&S)Xܾ$7K`#֏*J@$^3 7ylgc,Q=CE$tn՞UգD }xv>КC/[F[wHlMʳ!0@N5%5cYu+76֋ qٽ!KfR:.2E}2wͬGMO,4O/`k۳5Һb$jQRk!rQ`mjg/Q0[ʆѐ+PCIb[WJ!4o$Zp̈!g U5pP6[WM ;<ЧEf qn๓ fzPU؊*1AWrwyG.&y#3E&dn.>n 2ddZwPpNDB v9~?â$?T}p⮮n_|U⮮*M?N1#AVkPBs $@$ܾXs=P >,h䚒6_@q,k~F{{?A:t'40k^R]MʹWx!"W.Y3 AFs׿,*-uy{?寞hvh %VnxuQaH&|~v1ol~GfQos};Kf% 2Io:> $S4rA&uZh^m{BH-u$~eR4vn,[n`aU⭃ n1V&W uqWWn]\U/qWc_Ց_Ɲqg}X* O-b#mq1b7{ob":w[yOIf؃~;#׀j&v'lkA9g%nRW[3kz6/nDJX>Ѳ$#)xY̹G(7T<6;A@r#ĭ7N.x,4}7Mnf-๘(]@:Qytz2hZM2YѮ^1JQudbJ$rFU20*0#"bcW X}#U8')yǙ5| V}^ml5}TD[kd.KM"U,] yoVvv$}n~Cr*[WR}"M"J\D%Qd ]~m$MDu`~'avSG/l. ?:LZ^KMdu+kar 4%†Rhd%c[c߳H:ߐzVv*UثWb]v*X.<﫿s[|_z`kJK͝CSѵiDP,V!j2tUÊc1~/okiGKq!F;K$jֿ=|'4fk:icL vEPxԒOZSm&~<3b;pFǠ5#ol+"f(Ě\V4GuMkijU֥keeoK9H JOL4($lW/ƞeKIBqeL@{G. TW&Ҏ^r%nG{Ṷ{/-I WC; Dq.{>1}/qM󤗚*[y/wMq0˨\^s`hin#ilcy ,`է@GPqnL 62xĶ7s>(2Gq7!0*6E?ZIg^mqs\56G3oHdR#!c.<_/t_Q)pfdnFcO͗Z5oˮGh2K84MJ)o9cb( I[o;'~2x9# tWs0=UhGRy( 7z&M6- |m Vd P@<Ҽ0W'$@ut 'DC8Bc>8VJ{G|"umGT&71i3ikze1p;b#aQ7$g&nBB@F[G6kiq}ۭ/4ثWb]v*UثC iH򏾰N wՏd`?:^Wm%ƣ~iV;R%#D $DZ؆3t {NjhrqxxN'ki0]Q# RK֝=c̉!d G{S^sijX|[XiRY1 Ujm#_J@ E}4ϕ5cU󖧭Mˣyz+F mn"bWe970uqgHzbq`vRɺW®*uqWWw,Urv~)c_2B&yG5ι=_B[/Aee枺- #FvI] Յ~jd=~kY@Ҷ?ڏF"Z^;!XFQURx +'[Pצ5-Cj>U][qc.)ww xfwBo̿ǁFI5CKoZ`QۋB)5IHVrm;U=k}ꟗ~Au]/Rurso-O];:Wvg'3\Ub]v*UثWb]v*UثWfr_yg/&s #ζznw8vA;fjaG{W~@GsO4c\0O|K/yͲ_Wr@`صD;}L~(|NlOS= HKڽLjp :of9ɶ\"W(dnOоOTaCmDQ)O!ګyTtkY}c]Ķ?R(5,XticQ7&T`e`nɭ{n:wc E ^ۿ=RZyUlƺ4s'u'xxNצXIXFFXcD`l V@Cںw9xI*vznkۛ]B f%j2kS~#hW"?bw?]5GL1LY%j-1?\MOڕ!$\r~'~@>]?s"Ӭ-4 -/OGmg&~Dy1,$#"IV1_Ձb8Xuqd]*;*uqV늺jc5ruoANZ/5?0j^q7^ia6im>jZ []b(Kciop@!ıqX,7wzg1|YԴ}JjԞVWOJ.$ziEZq;nSW/:o^]pJґEďM(S&~M\} Jvzު$}kSӾ+髮R{[R5]=(}izzhvg֮gѶEst3QII$]v*UثWb]v*UثWݫI/__ܭ?)WPZaY˧vPY Mk: |qiNŧ60iQWҵ@zԜmi1 *0*8d1WWnlupaC"źqUpjUثWbZ[_jm4C!{_&]v*UثWb]v*UثWb]v*ismtv<_y7+O}`k@jGiE;Pw2B'YL92Go_4??`T&~޷VSQqI,*64\.cݏ$r ynt"Yٛapj1VV ŋubőv,z*t8X\R⮮*Opum[4C!{_&]v*UثWb]v*UثWb]v*3r25ME~a y-.ג4R䷬~߮n>Ab,iMǙ'o{R-ʺuΟHڅS82(g(nSj_g6SSR #Awj{/K*;8[QX ' CÉ"JD7Ke+|+h:4/h:(Kկu ɚ\ O_3ˊfn4:,y v2~y;w"6L53&KKLxgEt/K~u~mi'oTִL}+CY~_ 15_]b7線A>f_y7/O赁ث}Vc[F*Uثd1V* i\Li  T5v,zUpqVZv(v)v(v*Ufm[$C!{ثWb,+1» v*Uثv l+®]qqA`tz|m?_ܽ?ӓ Mb߷Ɩ$E4q6o" |?hM3ǩlg/I)7߱󱕿heg~CUqc??ꉷ>u0Nxd-Y)Vx6_J6sWgUUO0oG^4e|-_?\alzhƕp WW/X/%އ?6/CU0oG^4eZHʹVgpٿUW/ˋeķyWg|-W?\<_͗ao/6o.CU/0l[gæF-W?\lu_SN?+ G9`ǨGU4z7/9`Ac!beꗿ<Ĉ~Xǘ{~Wv&6Vݏ070ݗ_Km[$C!{c"UƸ[[ڂ68ӬY@8 gIm[ҩF4dk NkQdkG4AZՖq~cH88Gwخ_dhxGwخ_dhxGwخ_dhxGwخ_dhxGwخ_dhxGwخ՚rTdz74!d#FSFah6_"? >gK(cҪ./ٰ_H?4i% UQ)P/l*zPX'7P]rOM9?/$i<Ao Oqqobw*:u?j52":)R3c֬#ֵq,[[_Ȭeff5ҢI{KY,~cݑ$ƞmr.% 2{3KO?s Dolo߆RouOe{~b[|? V~¶[qΏK?6Ͽzu ?e޿m[$C!{ثWbrQI,QFUTTN#9dh c"ܞO0տ9+t%şfcyg$:\\-q+ oxc"o~[da9ߧ2Q旐<ɡ_˞No4kW&meu[Ś[ąBz=C32{<#"Nw?Ld;Gv6M|>>_i>"ˀ'M9R>axcצ>lx̾dY;U#uAAw\wb?[oO_/YoJ)Dh݁(ju~iap[ q:< &<>fɓ >1W:܏4 {X料P.&( v#*Ӌl 5b%vLQI_Bϗ>OEzì/ʀ_/}R4/j7 x|oazYm|߮nJK4RF!ZO'51;[ۆ]gfLa(X,?-R[oN.5K]CFf)4vP^\R78YOƵ BG!&C |5~|XW󽮯hVWYN7*G7,b2xԅ`iLMeq߼muȈ:m/hOϝ# B;#yŬk߬JgNSBk^5kNzx#\x7|(Pa#Gaqw O0 s0EwӚm4 j+rpK Ey:QώCDo\lB='[|:VrɮZ=_\uM>32KQo/'-䇘4[JM櫽F[֟FUXH4EKU&~!| &2''v; rj'S%)R8@ٗ[ FiϚG4'>kKxơ `F$Nd$e4TfV@r:BW.""OQ'rh;D οF~vO?3ө>Nu[KmR-jK{]V-:F*Q# +14X'" 8NK&#Aqn}؄CP2;9*7!QQt/.j_:'+SG[.ލ@A ?si9?؟Q5Nq ܘȄGΓT3ʾ9IuV,i34LG OFU@xL39<9xG=4fn2ۚ13PN1t#C?lκ?}69MZ_9i~IM͂(ྣK ԝ2?H1||@Gsn~ʸ̶q~>D`@wu*o~.~Ya/-K& V2v]CM k~N"~G嶏/?/jߗRzֵgO]ZXLF l,f9G/''٭>5b8}R$/d)Q\GڂRUثC ^JK3[<_ܽ?ӓr116ZkdZ5o-㸍݂+KZ(yI@1&&uSSSf@~刏 o@&@/;yKc⸷Z`":ܱCv$8Nj UPqZ^<ŭ Z\P Z`[;Ѭ1S >ESI-t;q4r5sFv^ qH'axN NM@C5w[fD<:_k:.-e/MK[;[xauY(bHD+Zw9MC^#˽}x?^y&ogioynQKo SZ\w2<п2\F5 L'j@޿ǔh(ۗ}H]9K?0jzp5[[-,h#5Z`)ߩ9^Lq]6&{#7W+cM8U^^\*gq#jݟmn{<@nӿws;6?k[FBH*M]v*UتGs@fw5hZt^5[X-&Yc ]*6`Wc^U&6_*7UkKOCѬ-F嶆6(^5bҪP1Ww͉ɼ<0@2,ثWb,΄}k[ItC5M9?/ _?UZOK,}JR >Y<<ѿm̟bziO%#S#،DuRV^JfI4摾pI||#ގl0bxwίZ%}sx|?˃?RxW_ L+;aZԕQ睿D~;cVO"';aYG[oVwE6???1+;"?QKnt( ~Hw_g?Rۿgy] ;cmR.YԶY{AŽ,@[w=ԋGuxl~c-VwE6???1+;"?QKnt( ~Hw_g?Rۿgy] ;cmR.YԶY{AŽ,@[w=ԋGuxl?~c/G?"?Q?G[H9WE"x.kqm9 OW~;6 pMF?|@&?F?#&h?F?&?F?#'h?F?#y_@5|G<Rnqc?#_=Λ1P_?=ԝ~(ƞ{7AW`QOƞz;AM}чD5x4Ij8y?@5M<Rvqc?7<Rvqc?'<Rvqc?Ny_@5x4I@5xy_?񷞿M?uxV?@5m<ԝ~(歡g L@IpN= cն +;^?Kֽ?S}SFtۏ| Gy( PA~b3Gՠ.vR>8eE>XAd] `GE8m% ]|;_j]|uN68ڻ_j]|uN68ڻ_j]|uN68ڻ_j]|7wV֑Y.Hf&'&r4-C!B#?ciA&ǿbz-K%ĄVWL %o>&J"k6{9m, by7n}SO֮mn45+8aFDAs=bP : $q dm)nzi0e"O*^n;ۮ޺'H]|&»_~=W[yBVjw׶{%ki!G繷S͢`8vn8I`7?;d?bgD=]ÄK`~v+&CwLĖ?oC'6SԼ<j~9?F1T'oaDȇ B`k30Gu^vڎƮ=1A(W4MLlo`Agr1R §tx0Wh8?N%ZS88888888888888 t_l:ʹa|5k3O'iDKEޤ~bS=Ϫ1/8y~n-j]򿗴Mz;IYˊ7)^7=GcLgU/?L. ̋=y7A u/ۭv2OjQ%}FD(WaAt-MD]Kdrɏ8K‰\sǧ\Xu٣"!}lq Ɵ1yH_ԯ$eP\eo GU(/'Ь,=VȾV{[,`p4>~[ݺMR6! >Ⱦ:b2iZoo|ǤwCӴBSg J%FRjH4`0qs<]/u uMx>)oquŕ՝ k8gW(U2@6#TH.o܍\c'`}m=.Lo:y* Ka}"L$kkgY3Vݧ-дe?3Xŷ#DF^$EQqzÑG&M($s?+xy̷Eӂ&7`XoZ++ 9` .*#W7wfVE1JQ$G]G_aUE뚏qkZOaC^:Ӈf.Vc2H:L( (V5rߨb,rDYDnEfG;*qyX֤m;5:zsՃ8hQ"x^vxx&U EM.&u19XKM&qj,BD,7FB /" OP.bA~ }I/ᲚP֯l uI[ht>Of WBo!Yi XS%A>{L#GwY}:U6]% hEoPHEv %`GBWCvÌ[. ׿pG:5ޥm<)gq_,K4b+)mEuN b$dI wvls- oaקpȡkjWmqB+_ )L:{Z=琉Us4!b };oCyZd-mCF-op&LFB:yokzm>}^IJ|x#aۨƬ5C]򮥫_5կIT!E 탗Q3)s˧ G^ !!ow6A\-4) o&P'x8}`9>y }SݓQ,y\_dWOl>TZ--֛;n]=K}wUu҃15ړ6boCga愹K.HqYWW5/7^F|7=xj@!d"Sg<&\a&2C'ik4~^q9B~7I_7y H>brt#oLDF\C^wT_ ]C3O9nQ } @BB ll[;RMj%<f}&Y%ˌ/>>uBuQ?H77 *&GY)A<葹DXkb&ͪ|k7_k{Gq=܄(9HoyH~)`y t1eDoq6Vm>/ú[w\gBx]˛_F\N.5=FU y43$uz?"Ez}q0" ;T*@.9QwG#W:ů<ᦏu)Ѝ.93b~b1W}qߘU]_yAO/x5-_˖X[k:ټr%Օ7,2[|шLl%F{:Yi6[k+xm Ǔq$3&d >m<%f"I>dP2}qߘU\_*/wUO;-KF쑻WڧBϬlTmbyi~dֿuOYL_ET&囧҃8<ˎ4XEsS%:6X Qaô" h?i u=8$Gieuu8쮮?#4㲺GvWWQHӎ?q]]G#?N;+$Gieuu8쮮?#4㲺GvWWQHӎ?q]]G#?N;+$Gieuu8쮮?#4㲺GvWWQHӎ?q]]G#?N;+$Gieuu8쮮?#4㲺GvWWQHӎ?q]]G#?N;+$Gieuu8쮮Կ?#4㲮O6q]]OgieZQӁ*sJb0;яIC!s2Ȳ)'_Wuendstream endobj 470 0 obj << /Type /XObject /Subtype /Image /Width 347 /Height 186 /BitsPerComponent 8 /Length 32168 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream JFIFHHPhotoshop 3.08BIM ResolutionHH8BIM FX Global Lighting Anglex8BIMFX Global Altitude8BIM Print Flags 8BIM Copyright Flag8BIM'Japanese Print Flags 8BIMColor Halftone SettingsH/fflff/ff2Z5-8BIMColor Transfer Settingsp8BIM Layer State8BIM Layer Groups8BIMGuides@@8BIM URL overrides8BIMSlicesu[ Untitled-1[8BIMICC Untagged Flag8BIMLayer ID Generator Base8BIM New Windows Thumbnail )p<PN JFIFHHAdobed            <p"?   3!1AQa"q2B#$Rb34rC%Scs5&DTdE£t6UeuF'Vfv7GWgw5!1AQaq"2B#R3$brCScs4%&5DTdEU6teuFVfv'7GWgw ?1ksq+p{A,kn%A֎@w'16]S 2$Ñ~ʼn{JkJU+Rەk+gX[$8>I{R5roEm} ~ ~+ەk)m5O-K8[$.\..ܯ/[KnWȭoo{I{R5rk+k8G_`@>pU9UY/@sM Y}5z9 {ZcӶh}ޞmjVbO-t!eaa[)hp;y82ca@LTOi-~Y?8AKEU59cXUYe5,ڮò:U/*6^STߔo.=QlU[Z\`Ik{oEvǞkk\ ƀߪ Az9}Ye5c93}Mi%tVfϡ Y MbUYgXT=]ϳ%ioh%k/phdcXo}$nOJzևѺZ$쩬n~ݕC\ZK\YUUe{xhMI/OoKt[Z6w~K7'?%TLsvWcq.mU&]>Z%ˠ-p}z8uVv8oK}\Ict5t[l__k-,mV0c2 mZ? ?X55Q<}e3nVckvڋV2lP-eo`'s\?z[ ?4րX ?yWU!׺IlM3} SKu?d@hO}_2]ii:][Zs։MxʛZm+h^{\V2_o!Zn6WV1dF5~>ѳps9/gγ}^J VF[ێI|gKu?dSNxK:ʣ(6 ~=YW]eճk]ǏS>kW?SKu?dHVcc2˞]qk]S=;o?{.k4R济s^a5"oj}e?vVckF8BIM!Version compatibility infoUAdobe PhotoshopAdobe Photoshop 6.08BIM JPEG QualityAdobed@      [,  s!1AQa"q2B#R3b$r%C4Scs5D'6Tdt& EFVU(eufv7GWgw8HXhx)9IYiy*:JZjzm!1AQa"q2#BRbr3$4CS%cs5DT &6E'dtU7()󄔤euFVfvGWgw8HXhx9IYiy*:JZjz ?Wo,~ޝ<,.WԌO \vNj'b>ǘ?c~?VR?gd{DƵ=WΑ \P>aZ^iA4nYYXM q=D%R{N>CsN'6!|@b%GߩiL~9~}KƟ\G*~6ξS[y.ï]@E%'`y:(5b~S!#$m4I<_Е"^ -jZtڽXyq_] Vݮe*B3 ؜941NJCa.]4pŏ1wnOA~aፅw? l+Aca]? A~Wz»6ރ 1ፅw? l+'㍄[_Wo n'[w?۾n6vOq﫷~?ۍ}]l-amWo n'[w?_V?n6Տ~?ۍ?cknOq}X'۾mmV?n6ڋX~T ĶfCQI&T|4y˚yx<ì6/aDf* 3X䘌`8z7bl|۠=~j9t:m EԖ&ުk1J?2b9}K6K[3i>]Nt%hdh@^Hy!`rPX\&xC5L\j6?̋ꝍ˛2c>|r5ΑwߕV/욟1G{f4ALё3|;mM,$;W3/9xcQaë$_ь ߤo"~v%ݖ{?Na{t(&A=OMhvN`vVXiDP#a·v=<]3]W%"Xy$Ldwۃ %)F0WDs98KH'%f/<uhhq`ȪmCUbM8F&;?z&lC$t's<‡y1_Ưe zMKQ{O-_s&EY_w3 lݕC)Q-d%qœɒc =0Cz|b1G'o!`:Dr dD1FX2`LSSg//'?0$]6?ə{@&3/xԾud&e3—_0$>?ə{W_n̽RRw/I7Of^?|);UA'3/xԾ* M|_ N&L>g/'ʿ?wd&e3“_aI|2KI0$>?ə{W_n̽RRw/I7Of^?|);UA'3/xԾʾ.̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3“_~bNIC̾_3’Bݽej.Rj-uedV"T]Rs"mD"" H{%|)y!Y_?3%j?B<y"m/]3Ț,0Z^ Ӝ~^`lj185$q{A_^HMS:Y sgew6ڍvԤB{:Y8M* @С`.^ VxqeGpJ侦O_֙OdN)c;OGy~κ]h-,6kؼlT#q1EK)K'yDJ YޱC\ϖnv c!d5ꣷu R#u2]ybO惥C>>k7}$fFbӁe> Dqrcȝ3jX2܈لGƤg<|@Ԍg|ghpUPiZgƳkO]'IV%JE_0;F8g+( 7`'8tiwtkqY,s K>EѵO&:淪jSOl5[[m.iwSRm~#'B4b},bd&"2g#c<@GH3fՀr謗. EB.! ״/=jwϿ嶧jBQo+]Ei?Q[k#FhWF9l|DN!)|nQ|7({Ut _~ߟoiӼ MYּ9g(yߧ=SiJs$QͪF«:,jFGn1ߋ xTef㌙sw1l q?sHп(ty| ͺN淶m-]-ܓ,q2FT3eڜq'<8È )p"!)JF@NCr 2U\1"{(W9!Oɝ[̖|e~Y>+UיZpiʶpz[I~jUU4O) <^ߋ'N#q)pX)AHKVs:ʶ]_zƻj(nE,9?s h+"S`(J&tQ 181(#m 'C< #2?ɟ7}>O&~Rj>sCTӥo-up&t`[I$M"4%UdKMqx#[u 2P7 Oe32y O'g`<[YlmӤYjYNU/`I7(JP$aiF)ˌHF?Ň?/<{y/n|iEhčIVvXnDȦFGoT"w0q{ĉ pqJsnApx!evy ;G JdE4k^qW-2yoN%kzm"}DY0DHhIX8oq"rqq`AŔLD#0=&ƆR3 v?C&; _.^~[k?g5O;~_3ko2vZ]ΙAn$c[(" zcQ0".{8!fC2Yb;!" I@ԒzI -/*2'yc?W܏?Ox~7֡j64%ZFX /ce',x̯q1#`Xe0BSV?Q}gagCߛq|yyIzc>5lL!4AV q]Ĺ:r%,y=9!"9DG>`h"$PGFw]JLcLUmVg7Z.5O1j~[1Bt,Y:␘΁$,Cm}u>4MDMf1e{5τH@N-1 )GbH/mv}3M&}ZϺn5h5[%|s#Iye1|@}tx=U nv#Q#D؞L@qLUP4%POP֟VG嶝y{̚Mf_0;޾%tZ.H*1 `#cO9R$a.qlΨF@"j8D/|ӠY\!yS^]:|'!If5;w3[U%Jɜ68oɓx<"2a 3g;&L~}_֐ ёiwqwvO KBA2Q~"5VO](\?Sm*kPKO(d![h黊0O;JINdq)]7Xn%aDGbh97x,럖>`n}uRDC{uanm{kgI$dV'5ᵂ.Gț"[6:|w0%ϗvSq ;O&CQu͞c{VAޥjkyܐK][a$zH,_ 1,ȍB`O "NBOp9Ghm0jY4&uP2k-͹j7mgIyIId'!UpzC\@Oӳ``y)J/ 6]&̶3 5=MH䇜WvΡuљ2M{il`[YQ Ns|O.C+)+᭮!qS2؉Dʖ>O|!-y;uh50k:Ա]F"1}ݢ*JTIrȘKkPxˈCz}-<${ܞۻ ?"ymOZuyVW[5SFim 2xhӫznʿ%D̽B17=&ʸ){7]ѿ$,jzO=障Ť;Rj~"_ўc@?v09W*GW~vxve`'|WTzjiڦjZ%Pݢ͸Үm. 3_V#!ʡu%F\T c(<2X G͜2J1kHX!/r>Q>i0Wf8,-fpF}b@8(9)) 1hNJPxb;:0;[Kd^u5!ZzޯqY1LIH,q>ASJ* wC,(/ˏ$MK!//:]B{=Դ.}-l*M7!9uLfCR2 e(OCQyL&qcxO~1-8lH/-w䟓147 ~Cί]wɺdh]&:3HF6(EXg)JG%9+.45qf-KP~=O#ԙrlK>]m6q 4<~WK-[/(]Yvy"*6+5źc3g2T FsK!װjI 5. ?)\|B8GakIϘ?)|{]ZV.k>cl5:V X IB"m䎨]MC,`H୸82L!WWюD0@ƈ<1ؒA c2yU11HGcB<:G]k\]A%䷔) jzo1\Wb]5k[yt7w([b%s}KuSgumcev3T),-Hlv͞)pf,U[e'7|ͦayMVo*[ySA5q#iuMWV$y(NMr(C~$b:B};]ibFrለTz_?nm}>#mghۥ'b#jē?>_#oHj4Z~CiZ4jZ&{q:lJm8K0OMz嘻]$a,S$)LA;6 $@|O8UOJ?kԣMy#L?n꣟S# 6#-#g~evi\ĿS,byըzWdzˈ"ep$# qCyv6!#K=oqv*@dTl`ú΋̯-~\Znz:-.q5<}RLR3<ޙ 1'Nd+b!~c`c״AC2|*5n8@N"{ylI:13J<2#$򯞵-hZ5O2j[CmŌ#C̡_4Op-R"DB^ZX3q<<Ƅz8BWN!< }O~'U!DBLX;MR7'_u=V[0NR6<1NXD_9kp+O:|gK7IeOucPХu+,qE- *5L(qJ;)1F#fxꨘ\&1B K@O]rQ΋d~bm[3^j:"WӼyi,in"9lIG8Ê$FtHHJ~q bXLhd_;=cQXl8!Te?c+k0h[l5o0-`sO{,YkQ fUg<9 qxā ?b BN#\0"~!,d2'yHIpxo/izΡG_2/y̲Q_0(hrڼ:3#hlէ̷ %w `h8?Qc2pF'}P?cˇs*xș<##_>h򶟢Ξ\vqd[S-^a4"$ª6< 3z@+زQ9(X%@yGj8ɘC7 ˜n(Y K IWw懘g(J}o6|Wu7>iWBhX摉1̬Xq^ !8آ+$ L23UOqFǏs&QHs2 ^ ~cZ7_z_O-N k7ѼApn%(rC@ N)Ö? #!Œ Ifx9 iB5 ;%#W/9[y_:QSM%+ z^^:"!neh z+fE(ٮ8wSFj($t ]OmbqF=?Ρ.e]]_[yFZ_K[%sO+ۏ\.C<&d)R9cS$! L9b#|siq[aYrX;ywv:v ^]cXGmH JN#ȴr%G,aUŰeO"Iq@D1̝25[ G7H󾜞|ީryf_6.]#<0o?f|1+'sc}f&>08yf` T!ˋ6+~d1*>iǻW4ɛ<}m3ϺW:~%柪4s:F7ݩ1`rW3 ܁3H>'7!R1N) 84#> #8 xdV^N=NO=eQo,a_~{H&]K}w,Q-2GIpgA+ˎd .2DDm#|N*kDLrw%[N𭍋5"<6ce KJ*v=ݬwK{}Ky!_]ʱ`YL&S&[]sCQ#r>rt!X\`/T(qw <.j>F|3}iv`Oom>ͷ53 E-rܣ*-:pOp@ӵRIKnQ#q}9C1i͚W.?6h\.FQr 8(\^!+v|OO&^~VU򿙵m3Z]>}{wwɮyfONQrUTEDZeb1 Дq$LGSKGĨd2\Cp@W f/KGSOOo;е/dSAn4˹ <{/e pZ1ˊx C|чǎS8b<_!M3dDÎ121ᑁqώ7X F'?8l4O'yLߙ|zfqh)m"m>EWkYZ1?31ZugQ/X+ J $8pv㭣Dqdo-=:mC.:GX &7 ㉑9S5%FCHpQGC;wx!?ȡثWb_ZV^s?.?w([b%s}e!j[.P=a(*ryQ4,q0]&CBL28!ܽ?'cut&*}؏qO}iZ[(H QUG@rI6[fv*UثWb]v*m-!kqq`h@#n " <C (q]v*UثWb]A}cwj6B}I4  "h9 >wm( Pl.]P'tY")X"dg&2( )HMȮm$X5 ((PJFDFXF" F"r,v*UثWտלOKw([b%s}e!ثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWտלOKw([b%s}`xmadFV*hT27$1 %y7~^ݖ*^ywT"V^Ki,Wp 2c@$XI1XefUثUT򦑭jOw6#jo"V8* :e],2CWw/=t.7;=Y'-.qOʳ#8KyS~V)& Lj\צWK `IK V'BD~ZFsW?-/-hcіH^D^r?H-oِ3  MT\d$,/W}?1VC8K3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̻UTƧeXGi~3.}?1V?_k˿_ykuOjUqyZ?2WZ]Sc^ּ̼>`]+Mmiiw5x%ܷqQl(&kڛ@k{eo0{1|Hwa,W_z6EY׶K'!w=àmTizKn=d:7{5k[yt7w([b%s}P害#G<Z}iyY/2c '/MV9fŀn3gÕN >eA13 BcQ#|> c58H$LN27 8qq2p݉/h~ThϜu6`?|iܳkZ.yYh0k/妐@!ԻUCnшq@ BĄG8x &*R#9\H}0eq&Mzd 2'ӟ?տ.ԹyX3>_D?e~cywO!Yֿqo"P`9"3Eը&d?kj7\|Z!֟S8O#< ^Oq܃N~ rŌ^m#q*RggDzcD^8S[ҵ[ +S|]CLFx+E2?Į m~Ԝg(AG~N&8#sϩgY;v*UثWb]v*UثWb]v*UثWb]v*U熱o~iךl͕Os\,3wZ֨+_Sd"h02_~Uh7êy0u20.U4T!jd$ωzxDne?˜Ouz7t6o+T2jjw=}CS-r_έv]W_w([b%s}H/M^q.j^YёfշGHM76ɽZ7u[ wL:^gJ VHg]OB9H?b A؇elv*˞e4<ݼwsl'K٧wj|SCĝ*Iqd:uO s Mc.|P?.c.^hZOl.nb-Y]/AAomAܒ4JUd-Kiԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wwԡi]%)j]wx'染׭5ct+mMt!iQ Z`ju S\t?gyۿ ;t1q?[[K/1XYhas$I:AuvlлE"H%X5(FV;Nc//j!uu::H pt P<.GШ~Eԗ/IKHw};C+7zO?g_C+?$4XƝequ}+J*^ו,F#)v69L`Ӡ1/!!G$iڧtVGO/c#30 h3;2&H`n?>OG/42h8lbEoHVb]eŏ6IK/p e>ddʌ)O&'˿)SQ>Ad?p$~Ly (R]UTTo@r2i` fe,$@&-~fAuo m*DTݖGm$i3Y $iK"G @6bK C##`F5h׸3Qe<ޙd_4pJ?S?hʌ)O&'o8/Y+ Y(<6ZXo ĞPc`@41i$F(zxo6ׂ_-j7$ )ȏDoL|(K| Qe<ޙdSM/4|ο.4;Bտ6|ڮ/y[:DUYuh?]ʋE^TVn8Q!_2[1le~ݯ5Zy˚,;˳No3jS i22 cqF1YC NdHX}?%ysK$|Zm,A'FЈ<Z?Uƣiu~LyGT}^˖^dY *4h H>g0px1[֏31[B緕zȏDoL|4pJ?R_G;TgGYO"7>?(K| Qe<ޙdSM/4|F~D'zgM7?ҏԿSȟMO4pJ?R_G;TgGYO"7>?(K| .yQߔt{o.ys=^=Om좽%0Ge +^)2 D@O538db6Գ-K_k{uw([b%s}e!ثWb]v*UثW7\Rz::5dH铯ћɐy>9vώ*ύT?妩iz$dDl~(} Sy"ʗUy-7vlumfkϯK2Jҩf9"8bv|;p pN4j2hgH`H6T*X7Ü?|s޹X眮 G-__My6OK-Y/q8+t}g&oGM8yWS+ח[q}S\Ks 4][敥hry-{:/5*R[ܻ]E,A$*[2,%$qfǒ_L$ I χ%Fx*"Fm88R'yo(7wvOˇ~N?"yG]jf_>MMUC,BKi$FP:)P&U^)H"ydž7 ᘈEF1Aw"#<^Z/^O3QkߘO~%{d˜]zc34 r9pb@Ʊ!F^'.|X񉘖2O [)tI2O d~ui?5,<2\i;+/Fѥh\G=_I|8bc(2Nl$x@|>@_cb8#l^J46Z:o2FмmgkWw$ߗƗ?7yc{:$S=$bᖣ@(ߪe"x8RQ#bޘgo=s!sC*O#7/5wmb~{}s!5Wl1c^Z} gwQrIB`DOd_qr '}˟"h_ea?h]Ǘߩk]זVm{@ޙIwo5֧o2n&^7>C" 2NG qN$G葜#>%Dz#P$)8>'FNͮXyI׃E'ѓ:w{jSo|e_yWZu y}%mru5= wW\ŏ@ N1Ö? #)ŒwL^Q(f.CPrX*垟~gɣԴw/TsouEw>_]Ƥ<cB 77&+H~$$2LG[!pF3&&DnQp>\iLcſnץd4/./SUWmT{_Jo90pK$xx #kc=s+­o1;e\PT}z&e5k[yt7w([b%s}e!ثWb]v*UثW̖Lc<27H˼#MVTGC9YW"R'??GC9YW"R'??GCbrȣw>VTׇ7?Oʿyw>VTÛ__q;fhGkÛ__q;fhGkÛk#rQu"g} 5K)GzN䉄D(D z姓4_,]ꚅ귶ѼvS.K[r$i}i7?MixPcgop|4_9[j6:qkykI-EeⲍBKuH#f\ κWqFwSxu=Lx`Mw_ϯ|><:? 7uߥ>]3x{//~wC}Wxu?Lŗo>_3Xxu?M/e:?/ }[xu?M/e:?/ }[xu?M/e:j4#=-<Ϫ7,?S yg[4_:ޯ굝v|:E$`BѥXv^$\܈d V`ivdoZ,tmoF.)2x.m_ʮ6C.)q¬69]n=F22W:T+Ru=Lx`My'?%:叙8 2i0l/h}+)"sFFªN̵gc_oJ}Ի?)_f:? e:ҟ_. }Wxu=Lŗo>_3Xxu?M/e:?/ }[xu?M/e:?/ }[xu?M/e:~|Խ#><:B`MV_k^vҿNyL-t}[k[)f,K%i zp9W w Yϕ=/fuo=Cw([b%s}e!ثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWb]v*UثWտלOK]i/n%t *-mԑS)c"D i{'=769?f~gGw=75??8Ipq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axIpq/;W o|~axտך^YQc}x{g?u?% <~Kwx,/Y_7g~n?% <~Kwx,/Y_7g~n?% <~Kwx,/Y_7g~n?% <~Kwx,/Y_7g~n?% <~Kwx,/Y_7g~n?%M7=_;2endstream endobj 471 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /XObject << /Im2 461 0 R /Im3 470 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 477 0 obj << /Length 2217 /Filter /FlateDecode >> stream xZo@Q[3STCZ6[8V*˗}sQ,l#4bRW#|X>4`hĸɮm t.)IV(,Lubih-ˌE׬]|Z kUBo&^G@mnXαsLTOZ_r y!4t?9@^nﶛ[8dדUT@~a)L\nujbIؽa, >]5r2cVׂf!ZX*R_}::' VE-_M4{^<k~1͑L5[yNofUbfVL@CZh*^.W^7X$&u$.co C80fjM5'4OQPꙇa˜*K_8 ƈ'?< Mo֒4Aռb/kXucTTX%&bN@~YaA8˱c~CBfN /SpHJ&M.'9Kq1 ͈=VĒ)zLZ/a -H@=Cy!1<>17qUyngg5^SY [A cR7hOc+'&F%T"hrB Gޭ/K1 h} PEΠ0G wɺ`^0! glpizYd,Si.,։Ty kF "Ο4eapƞaKaK렘]26~&t ?{]c0X(^\6B6NH:(X42p\K@VUPMir5%mcGg/CҨpzTc@VOKdۧ)O֟r NVbc?g  ŷ~د~ ݩp7ZC'b}Tou$]e+^["WaPΡuI(̲k_ HDlK4y͟#wǚ8HǹZ5.rT$^VX@qjU*ߡFVauX 4*=U*-p$ RU&~?@P55gUAg- /=T', H O$ZΗ'B]BJHC]5~F 2"a{Q3XǹqCp%u4|猀y6cesB+o+"'*2)-*yupw*+0{H+4ۄ?VG|A'lA$45=igOAt\bk~ Ý_Dm=j7!C{ 3(=~]K^ZʼDyW.9B|@'kBؑn`!ܸ ˆA] ⩤"ǻ?Ɔ3f˺\uw4Z>]*ov9_o> endobj 26 0 obj << /D [476 0 R /XYZ 72 658.6379 null] >> endobj 475 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 480 0 obj << /Length 1667 /Filter /FlateDecode >> stream xڵXێ6}WEd4EdA$A6ݗ" e$g߹PlkIp8sxfhHSI%̒L&+y>SqF&FHg<  JPAn*t𯗳g&J J.y(q|<w6c!/7t/(1r{\xSй=Z2y.\ձU/vmWl6Jw&)02#}y'%Xr& O#E|H3|9 Z0u0LX N0`D@FH"5GܠԹ:xW!d`&!dPFڇu: bWSUPFR!A4#R2>BJD޳"u|B,#Ͷ}'^*^6d^&xտT };>*>Ɗb.d2.ɧE,v0MY,yӧܧR 1UU-P5C&hz8.q/)ۈ1ϩ)H^HWx!}5`=J!,oR],~kEn {@N1>z ZrE.@PnDgHBgB͜!_ zz~p1^9  'i؜b ? ]}݌|Yȭ?>%FLYEEgkd'1.2:{mFt9C ^ӳ3@ 45LoEQ"AM0 OatHLqa)%tM܇'}_˪Zˏ}<"'^B ?a ?k#V&F`'L0B:-߼K_LX)AP+p'j*uCzED( dOi.Q,?$S.zendstream endobj 479 0 obj << /Type /Page /Contents 480 0 R /Resources 478 0 R /MediaBox [0 0 612 792] /Parent 474 0 R /Annots [ 481 0 R ] >> endobj 481 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [323.1858 468.4201 493.7543 481.3217] /Subtype/Link/A<> >> endobj 478 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 484 0 obj << /Length 1570 /Filter /FlateDecode >> stream xڅWnFߧʘ91ક\7mMԋ$.2 [`̮75safdß \b-~$)|/lDA~٬~*Zdƹ`s,Eb,ؔ۷7m|\ݼl&)Aca%bjlfIY3^:qLRdA_3ռXTۙJd}%KNi"KD*Cg$Ɖ$Kܙދ'a]T*S,.=팰qZX#_a*ܬ]Ǯ2̛!Fh(d@؈TMnUK pL#W#d͜92YZ kUB VM4Z@]Px.hf2GZ0##M8a<"Q a]O'}=Uk*k ;}ޖԭz-u݁<۸@yU<:Gw TJP#d~ˊYÁt %ȕb9cB,X?L@J-Dkhed hXVLu/d_Zِh茲8k3/wL, T|;m$U'J6'Eo͔ђI޽jFRp ^]Qf AZJ*8A(mpS?^C0[k1q0'5 Ѡ*:pGU'I$4⊱Ty1Cg\^tqo8tq<mlKybe%3,W.enѸa;ݏ;X;Vizl8w-Ϟ* yn'[r[a=0|cQ{A1ə+CTd q2)=/Rd' YMacks u? q`&Y!*ڝ̇5v*jlcL)V4Ȃ˗CɖwcY;`ܢ"¦O%j*ّ U/pj8D6nV %0v/~oq -Ť2!&$#lfM|dZyz 4{v0gYOwMCQ럖j< OE2٧b.7 5P(̈$[̢1j8Z?)H%܂g: -ZH'n(9F^tp_10p{n? ȟ~o?^lp xv-5Th`)XJ8W،t TA'A\r'aG2T߈eqmxwkݽ`Na5 ء i&16|6$#͋{ch3Z~G MtXp ".6> !evu8(Z-eDyҬ>^> endobj 486 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [161.8971 302.8219 342.7308 315.7235] /Subtype/Link/A<> >> endobj 485 0 obj << /D [483 0 R /XYZ 72 702 null] >> endobj 30 0 obj << /D [483 0 R /XYZ 72 680.3998 null] >> endobj 34 0 obj << /D [483 0 R /XYZ 72 375.1431 null] >> endobj 482 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F32 324 0 R /F15 309 0 R /F51 451 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 492 0 obj << /Length 2659 /Filter /FlateDecode >> stream xێ}P 5HI lEES! \K3VW\I^s.$%AF;υ*WYh+v'Z0J0!h,J=woDQGX=<2 P|7RMt'B|wyd4׫)K7)a =n-ep~HuǡF/Y"DVp]&yW'Da|Sv?<ޠKBFaKh4CtJ `(/%eWSlWo0b=Y \l %*ß^80/_yp+-s@Ӯ")oIH|Yz?tf;T '[W;)<5OoZ>Y5\.R0'Mq$"ɛ~-Ft^4%x"5 @,8Fp1;:$x;42x\j'~4ر!b1M 4Q]rV< wjv0[ TʱC d^2Ӯm3 (:Fڥ̓S>M` '*@a ( 0Mjx)ro)!XSxTRZC,i&`U S=Oj1"9D9 J, 1)t(ĉ] Te{B2pB$ -=$i386H ~m 3rZӕK-ۤFG [dgMlCW˲xTjyedm'Jɾvfv bqTܧC](K$Xq|0f(Tp?%Y%XaءUPHtXB^޴+)zĝo ӇR"L'V,dGaLs0sb/wt|uCH)W5op(mtQYF; )쀫0U>Ho߰O]5QL|eǨ5 02Lfn]qoDX4RdVfqj$ΙHjMS1.~EGi;,gu9b/p%7U3gθ]PvXV8L~EA㉧`0IѴ. 4IR"ǿf Mq2/0a[,XM' lgKsK̞HOѽ$).#A }[qMŗswʅ(j,cF~$W ?ڴϗ*JXqڽ:Kgݑ߼,r7"q?>b>ߪ~L5y0Xo=r҆n~x.0^Hi,s*Q|0a$V\{ZMf?LAsB\?n\'qK`0Rt+. &.>.;P! #l$z#.$qWgϝ(y/s3Օe*S Hc! 4bR{ ;ȩXk_r\pV3\ƞNw0J߷T*o2WqYpǕ9%Q\.>*aqr$r KC ]HOU1;{kDuU}r86տ\qkR_MzچO^ѨY>L؞;&rm~(\M50_Lrl0x9_ u̮̾P$N$^7*2H:=y(Bݔ~ƷA'R&ƮnmBc<`8sĮ%i, 5e_8- Qk'=zXjpҳ}hg31)He[ˠ8Eح=Cg\_ils];t-JX]b. ϓI\k2ƂBN]5z IVN+?mY"q]U0`ݱ BbȚW -O*Lȗu%CNQH\^)@0J{e=q)3DRR]]id> endobj 493 0 obj << /D [491 0 R /XYZ 72 702 null] >> endobj 494 0 obj << /D [491 0 R /XYZ 72 680.3998 null] >> endobj 495 0 obj << /D [491 0 R /XYZ 72 651.7152 null] >> endobj 496 0 obj << /D [491 0 R /XYZ 72 614.1425 null] >> endobj 490 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 499 0 obj << /Length 2427 /Filter /FlateDecode >> stream xYmF_/en̒@ndI65C.0Z[cы#;d&qnVRuuUuSmO/`rW-(_-|FI"ޏ|h`vKmWW'o^})SLbR#a$Qi&J*os}p1c\jC{ބ4}V9O?=hW6#*HtY-Lra ?Є9ѠeFQSњ Akn?Wt2>wYY{fȘtl}QhlҜb/dl;,NYCgY_:Ձ* d"Dj >^8Y&1hZolb- PYS BCU094^k>ӓeWirg [p7Q@f/wUQhgĽ#wG{ny6`'V[4ͩy?s8q0N8t:䶆 ͞)a0ʸ86zZ$烔Q7| iӘe=A𽐢CR~ͪS)4dYY5]/u>qqp/>۽+?M2FИ5~h㱀(+?zf y%x/',bl9",؞eEFaF~\᷷ՕuzU^A,{\/3/NPV]_sMXMXso9k#QJY<8v)'̖UVY5t@| ͅ](ܕQ%( q7p%<̐Ez᫛^T:<~RNu],#L|R/uT2F(øڂij c``AG'FG0%Q/1F wP+sˉX)` _a6!0|]xq:~ -*::߯ `-PYOۻfZAOC5E(97_ɲ1D,Q(CQl7sVELl>}B= )f(!?ո]TA TV083-UG{XNO/>~~ʑ^"8ts=Qqe<d͸,K`&#sX,{_V ͗FC^OIR?0Z[Bc,mû,9YNOǦ󻩯;Ӣl"v#흻Ģeuc'AQ϶ozG7LM] ߉p{{{)+^[ȭEޯCh(Lx۹:RwtmNev#\y_B_~ r-UsIhsxmWS ȏ"ov#+EohUlh_:P:pڿv%F6f,Yendstream endobj 498 0 obj << /Type /Page /Contents 499 0 R /Resources 497 0 R /MediaBox [0 0 612 792] /Parent 474 0 R >> endobj 500 0 obj << /D [498 0 R /XYZ 72 702 null] >> endobj 501 0 obj << /D [498 0 R /XYZ 72 637.8993 null] >> endobj 497 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 504 0 obj << /Length 1895 /Filter /FlateDecode >> stream xڽXo6~_b^Ő")Q)ڇm@C-Be+wC*";9lpf8"'4RÊ0J(eh%0Тmy@EdnuЁ,vdIm XvͷR SFe%D7wcXd&[o9BO#ؔR0]}_K6\GҨn%or0S<[V,5t83JTW? zh.X:J%SZ 1N0z"$ d562%B̈4 9fXx:}C]YE;lGB,z/ŗoh|IVWUGcS6ߖnI˲;NyEhWRCwRY}Wɝsޖ[8rh`0NόܡMPDU<˪kgoOnq AgK=9mQ.?Ƈ󓗬._wCQO5ukEy~vay{֕5ψ>bGLTl0r^=?fw?ߞz3E9=tSu@E7A~Z ")Da$cf#)\Mls0:N?Iq؞jY 1> s52acf3(6|(V|h178 %Kdf/ =n[8j)l 5$~I3 7?6k3wt텷SMsċl/͎nF3MF*o[X~md8rI #Tz1]{e}?-nW.&˦nbl$32Y$ۖD5ERs6il6uN\;p*-`B6c}߂yHȒ}OYFDZ"uېȝ')&L0me#l DT?_CI!2\@1/"'!wap= .fTKzeEeO! yknsl9b>WO1T9NJ8$JvXo0!Yo> endobj 505 0 obj << /D [503 0 R /XYZ 72 702 null] >> endobj 506 0 obj << /D [503 0 R /XYZ 72 299.5353 null] >> endobj 507 0 obj << /D [503 0 R /XYZ 72 276.838 null] >> endobj 508 0 obj << /D [503 0 R /XYZ 72 254.7467 null] >> endobj 502 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 512 0 obj << /Length 821 /Filter /FlateDecode >> stream x}UKo0+ƀ}hJR6d)쫛73|~'Ba xϧ@*sio{\);Upy%PpfꞪxĪoWחW:i2|\hLntxXr瓦Ҭ(>fai4W$*Z&mSJ+N[:,3`4ڄ@zt.MsMecCem0q]},{;l˩}(F3Mѫb`1xttjlY予bj[4참. 8c<XBjGG25YL:>o.M;=0.$p('+M48'h`\GD[Z]DۑʃM|/oL*6vDva Fk#Fʉ>m灌 b7Ct%(F8zgLWmד=X|z!7gbQH"RSB"ڐh)&Ytg_؍a=8}"GyGJRmk%Tpch<`ݔyZiN,W7O!YUq^k9miX>>F)C;ԃ뾚rLd;{W4%Wbtu* x: S Ks!^y> endobj 513 0 obj << /D [511 0 R /XYZ 72 702 null] >> endobj 510 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 516 0 obj << /Length 1681 /Filter /FlateDecode >> stream xڝXێ6}W$5-ԭ@ MoIH򠵵kaeɕx;7J6pH K[fw3?δUAlS^S1L(AOr PHxv5[#O* 2Xm_?^.0T(U6DQbj8&MUgwzҥ 'tm1GY$Um¤_ͳ?M[ϫ$J+߳oV*ʒ; Pafnf o^ SNE6@їVmg c/4/d=>q(La*x_vk?_bcOGlXɖ'wyx)?mA=kmPamޗ5lÞ:V|N%,W_ظFц4mD™bm-yS (6*YH(-T=DߠUߑ;JΨ]JbT/5"NABרU9ḎP6RibfrtiG-xF۱v;|m0{'e=Yߋ>o{BǒQihhT_ rd>Q\rZebceaEX&?D%YIvEjCہ5̙Qn,s9Jr#RїT/=W黦:ґoDh$aAfEey#68e_PPnIFZH *XDDژCRKQMU5P}2t,ry3Рm"NpURLpd/\\3Tu/v$WH3ݩp3B8©o0v, s6RDy Z+u5CTA˓;rTA>vf_8B&3*M+e<ӊqt̞nnf D/r<RzS̩ҁj{_F0FЙpAR-Y@ie8$u4̨w9?uu2 RܿXh+,k92QI(};jM=Tl}z{$!'fo'~f{R%oTE&닧_gjYO,áR 82B0WMmXw"+/ׯ$UMcy[6S2xc6CY9i:gs6z}EMy4p^y*ܙ2 Iiϸ$u9[:T%wz[ԵWK| RZ%7 _ے_$GB-{l[mL[iM+qq@g0 ;+MUk̇1D}AXhɤt`gY&D홬hץdJНorP ,l^aendstream endobj 515 0 obj << /Type /Page /Contents 516 0 R /Resources 514 0 R /MediaBox [0 0 612 792] /Parent 509 0 R /Annots [ 519 0 R 520 0 R 522 0 R 523 0 R ] >> endobj 519 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [71.0037 447.162 275.4511 460.0636] /Subtype/Link/A<> >> endobj 520 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [71.0037 426.4124 342.2694 439.314] /Subtype/Link/A<> >> endobj 522 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [71.0037 327.9053 283.3602 340.8069] /Subtype/Link/A<> >> endobj 523 0 obj << /Type /Annot /Border[0 0 0]/H/I/C[0 1 1] /Rect [71.0037 307.1556 196.754 320.0572] /Subtype/Link/A<> >> endobj 517 0 obj << /D [515 0 R /XYZ 72 702 null] >> endobj 38 0 obj << /D [515 0 R /XYZ 72 658.6379 null] >> endobj 518 0 obj << /D [515 0 R /XYZ 72 519.4832 null] >> endobj 521 0 obj << /D [515 0 R /XYZ 72 386.6772 null] >> endobj 524 0 obj << /D [515 0 R /XYZ 72 267.4205 null] >> endobj 514 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 528 0 obj << /Length 2060 /Filter /FlateDecode >> stream xڽX[~_(@dhרM AZJRJQVHZn c@8sf1RFݍ60͍yJ`zwYT'|ƄhDw]uw_q~(S>972'yw>_<΍>Sij^oŧe>]I|ꚶZ,M\#TFymI7Th4Yn|O 9(b#&I9I~mK<_ڄ4- ?;jKL9B)qp6~@RnzfGvg5P,l6EtYPo;{wM Sej/#eԺ:v`98u_5I)3`/ܬY4>N&)qG+p|K`BUdlkh5JH?e޻qDRyk.ςs Uڧ:(Mi%͞xf@HCBaOZX#:r:6h70nn}׬WJYońL%7#$ p2-2r9Il&Yk>~bg Y*rY},/R#! p J<֥#2eҜ˷{MՑs8Rzz ]\KD<[HPq!eӖG1S 3fh{HB+̤sn'!/ ذ9ƫBՖXs{PFvJN\.+Y}Vs<"lgΩH]L[޸^ ù-ʒAQ`5$'(: Nn4f㚣9 ݋5p%-eW1FK,¬u=+^T#c;QJ45{JؐPe#Y׷|9.mSyamS@_rJ2V"xƗx ݲfWK6= (f1.lMQj<,|6@8@pӍDpr;fVP|;7xBaQW^\C,I?'f:$ 1xX3 0| BFx ?7db(< g|yP 3c!Sv229ABP I|&u^`Lj(4ܧk8Iuvi;`33anZJRn6@Ps^c^JU.:sUx)>˔Nx9ȳk_0*<!C31)<{y520]gt?gendstream endobj 527 0 obj << /Type /Page /Contents 528 0 R /Resources 526 0 R /MediaBox [0 0 612 792] /Parent 509 0 R >> endobj 529 0 obj << /D [527 0 R /XYZ 72 702 null] >> endobj 42 0 obj << /D [527 0 R /XYZ 72 655.8483 null] >> endobj 530 0 obj << /D [527 0 R /XYZ 72 296.1599 null] >> endobj 526 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 533 0 obj << /Length 2124 /Filter /FlateDecode >> stream xYPDm8}qZ #HS@xry!\w|F)8cvfvfv+ISQ\hwY#/V قD RP@\f=ճU))t*ܲO=iͳORp+@XcƢ-DbcbL|ݽJ֦&qY|攬U=shWJXɀ~IF{ꛕˋ:RhW貲Y:z>Y<.mX6h 6NШg/Ty??Cv9Ct^UbAxU VOWg R`t?aWy(D!7=8d*lj3v*&Q#,GqEK9!B܄ih2 ^N/ +fxlFd`vȞG JӳmvDpEd&@y`!UIJ"K9 qd]QqL;5os aS`ƦFv1l&.~O (U!l* C!E'B.ŴHP#l#R GSdgW̐8O:* FD"dWSƼJ-{7~~Ty(vJ 33qF[ L] ^>6>N߁vnM_2, q;:#3D T{Ut +qkGzJIh\U!8l'YCPӛ0$xbP?RFȠ!k/v 0*qzҩ EaX @< G!T^d2h&x?7a'Y9%0I]6vп,+E!\;q8e&>8\?gb'Ot{Pl 8{Ȟ"]_GÃS"s̆3]p%~zY!M_Cy,'"[j{7|eq ԉO8_TS-˻Sp2FROc\-bbE[)l,$ǰP:k uf ( !3sWK'?i-ڃǡn:TH>'NhM i9K @VȟƓ2rɖM7endstream endobj 532 0 obj << /Type /Page /Contents 533 0 R /Resources 531 0 R /MediaBox [0 0 612 792] /Parent 509 0 R >> endobj 525 0 obj << /Type /XObject /Subtype /Image /Width 994 /Height 424 /BitsPerComponent 8 /Length 13871 /ColorSpace /DeviceRGB /Filter /DCTDecode >> stream JFIFHHC    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222"M !16QSTt"237Aq#a$Bsu5CRr4Ubd!1QA ?*дۖo∈KsRWѶGI7[Nj9;w鮿ilƟG杶뇟o?{Un.zuxc2QW>.zuxc2QW>.zuxc/ūu\rh"#rOjyzjw{Ѷnzȸ"ޫݳfjqt\ѵ5'g7~[G=^:}3bk.ݪ_Uri߽F{&;|RmM{Enqb.UUvIgh{6\$dovQ]|U1z'lԺzMN(h5[U]Ŵ'Ů.]L[]˵rS=FsM[vc7k>S'i6܊i;n[ȏMݷUTEk~^YiI督~ޭ,$9scWvfv;w/y\YvmM]sXahU9n\4UjnTG/m3ٷng=^:]S\]ɫ~ؚfoU(^uwEU]b왘jnѶ񷏇w]hE3])G,S~\'˦#馺hNgW%oRõ^DWOK35QW'Ѣgy#6U\ʧZԢmMڦ\>mSo0.>UsL{m;ռoH.6M7hȹ]z{nGݿD̸$*\S3TGd5tV&eq4U~7&♘gʋ5\[w?1*ħS˳TWmTNE[}DObǞM[ykԲ1f&(jji'xܽu5ŷ{27EqTLWWgx=:>VMv |Zeb}c]㶹߿ QWͪ>7w ^#Ӈ3⚫6s5 x:k݊y(ꙙ")&fF: WS]UdQMv-4VSӶodL}FڪQ_;w;43T'.tl;Y)5L4NofӾ_ucRʻv>e,(r*'wx@afXV.ug4;STӷ֘;3 X?.zuxc2QW>.zuxc2QW>.zuxc2QW>.zuxc2QW>.zuxc2QW>.z5932kYxtSSg}f[ s۴ j-O%? DOd듹{z WiȜ;nc^˱w/ZUS44\ޟ̏ˉ1q豑f~rf4ř~Zzwk7{wqjb"2#"1jaw_߈9um;%>M_մسnݧӴۉ^wاLOQzgїfޥFnF%)皢mtq41G/4s3YOe{NmTFY{EYtZ~]仓U=>NfvQ_=4Mkf"D6a_ Yе,SN-٣MwmWvmqz3na3][[&DUyoVTvDpD?t\˦b&jyibz"g&*,vzsbgaf&-ӿlѪ^{[Võk/ntdޮͫEi&;s=G~b,fiZUJk^âL4}3;wݫ|ԞX3=ڣ.v^N4|?26tVovźf&jSTS˶311CnUoW5NLO,eh:6/6ڷôƚhƿ6*˹~gǚ545UTDMuwfbyyp?f{OIqkpͻj:mɞK5ZEʪviޖ\mT]ro#.W6MsEw&"oW="憺t|}bqժ(r(>le\fffgj|N.ʲoeS5[=tDLL}hi剧 uNbbdZnlh#W]s~o11fv8*Οc\;-M/[+rc}r6蘟Ldt?"VE< r)ɷMvɮ[hkm۴4LZ,4iӍT{߳rkwr7vD8uNbc^T۱LFr֊ުbv숈LnVbjUb܋o3Vgif7bf}oN!f楙zCnvUSNSLTUTsnauibW Nqyz~.QEʧzj'O{r6|Z@ܦj(]O tOH-hz]V]گWɍoMUM]31To&6{Z~.s"l4FGkk,֭DU|.s]5+y&VoQs[\t^'6p*V5Y6殆昈)ؙ;?0tv-ՙs]]wi^v>U1T:^9ż-;MƱsjݺl]kv3;U1ܱNU1uNbn8oS`vQ/ILw"ꯛ{Tm۴v33;Zw:MZ}tb[˫]imWnjjgh(")sBNbSG˪)șsmݽz{%( xaz}H-MTcωEzȍ:CMǶ X^ӳ^ŷgU<*ºL8w{iOzqV1{3\#֩#hlD~p_<0=>ĥO 4OO)9|{nGk?킢/zzse'x=?A觢z?!X)ᆉ>%( xaz}H.>!m&ct?؇7ݷYl{Г׼k( ={F2?T~U`K')ᆉ>% ?؇7ݷYmhbvmg>=TP[EBO^{?ѮL4^$f8oP1nm?V{Q@j{5M݊Yf&=Is} Q@]m %nn.4mOd{CEBO^{?ѮLȪo^Ȫ箮cyّ[?HU/žhcRK'bvmg>=Is} Q@]m =wF2{Г׼k -uG*%S |JQ ~D\}CMǶ4oo6*( 'x=?Q/zzsdo -O 4OO)D%S |JAqoo6ۤ9|{`.ބ\FhIg5yT~_<0=>ĥO 4OO)9|{nGk?킢/zzse'x=?AQ@ ~DB_<0=>ĤGk?MCMǶ hIg5fބ\?H uG*%S |JQ ~D\}CMǶ4oo6*( 'x=?Q/zzsdo -O 4OO)D%S |JAqoo6ۤ9|{`.ބ\FhJkZu48"=Y[?HۈETLo O 4OO)D%S |JAqoo6ۤ9|{`.ބvuۓcܪhfgz/zzoù=\[+]MTE;vm=ݛ]R~@*%S |JQ ~D\}CMǶ4oo6*( 'x=?Q/zzsdo -O 4OO)D%S |JAqoo6ۤ9|{`.ބ\FhIg5yT~_<0=>ĥO 4OO)9|{nGk?킢/zzse'x=?A[?TX)ᆉ>%( xaz}H.>!m&ct?؇7ݷYl{c^zޫx--m "5ۮ7[)Awoٻ]ɘx}VK'+;q~?H.>!m&c}p3 U+3MsN{Ω=͵?:zYw)z{{~S .ބ\rXyٷ.M8ZyfӾuL}?'?21ūZ(ɀ@[?H uG*%x_Ӭ|JQI^F\6'A"#^""6{|wyw_`u*in׿ShXF<-Z{q`zTX/n>%( x[zuH.Vp~J|ww٫By+f(&"{F{] Q13*<_$<-Z{q`zTgE\sz߷~}uzL bc3;.zQ@[?HU/žhcRK:'Ĥ4 SO4ܱsjM3Dc05=K"ٕbQjdo\qhƽv\UU樦{]fvǙo`,ϵgiZ]4ώ&"{?гniٚn]-oD3=Iee}۹(i蚹|s;>2neV]kw"+iYo -O tOJ!/ž ]HOߧq}殧#zwǶ'UIŻ^Evg}"'u}|/we:gWZ};O_gyi_0->u}|/we:gWZ};O_gyi_0->u}|/we:lw:ϻrh5}?sT6Z4YwfvۢvL$F=_gyi_3-> WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|gho7k#*}m}d_/EqDnc2?3ߪk(~'7 hTQE􎒚9nSrg9fw=<繱;E:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_3->u}|ί/we:`WZ};O_gyi_6vg]iS5}Wݦ7'ݹomKYߞ[ ~}|ί/ u}|ί/we:`WZ};O_gyi_3->u}|ί/۲;ݵ]4۞jhdr~ULt}̱}Hkjnz꧖kG4O{}dl!F5Qnendstream endobj 534 0 obj << /D [532 0 R /XYZ 72 702 null] >> endobj 531 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /XObject << /Im4 525 0 R >> /ProcSet [ /PDF /Text /ImageC ] >> endobj 537 0 obj << /Length 1665 /Filter /FlateDecode >> stream xڽێF_K#,ՓTj#5mMUM,EUbZ\{.ƘMmZ̜sQ?Q(Xg2䗙!I'jӛ3D,bz/ LUe-b~~?|6CDĤ )~@^MԥI046y]ۣP1c\ZkW p9O]xlz;_05c+%(z9¦q"E&it^#a)Ja#a-x0S[a *:dnp{32EkuXoJ2ĺ\:!2"v>,$G0cQ`#i Tdu!\EE_d\$$I8nWP68X8 cd@+q6`I}3U詐pXūGqX̣JwPP Jnݸ8igcφ^jQ9^`Ńw>{M%Xh2,2 EH\y! Q3(\İ*c"6Ս {[! QVGb[ lV|8y"t `%+19n~V EUxAEVx7mYn=0YzV\̡ZX(Z7C ڄ8s0 Ya!0Hؤ% mPv䇖%>u'#~VdR &Ơb8JeP[sIڬFe#|TfC1dD|K>+ S|x0pk! Pn;FP~P,a6^> endobj 538 0 obj << /D [536 0 R /XYZ 72 702 null] >> endobj 539 0 obj << /D [536 0 R /XYZ 72 617.0653 null] >> endobj 535 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 542 0 obj << /Length 2529 /Filter /FlateDecode >> stream xڥY[6~_} Ԋ(]4EMM EٖmmdɑH˶f6b!yHwHYjƳ4g]4B;%#̄Qb2 萃| XbFg~p3yÆwF1S&r|w6YI;]pLh=ʘ,LS]Jnup\0_< CU NBŤw wQh4qI2ר0u(k"K<>+9/bk]1G=:(x`Kd5'ѱbY# 5 ]U8gqFš%r&_`{֠8EaT7/_{mbqGnmqFD8_kWS8E=:4MN 26Q}J1o"f0)ݗʂjOF:~ghyNW77슁)k\*x,@l-U񶟏lO8§Zs/D"eVPM? ZE;kCaby*'Q<(Pm)y6kM,Q}\ QJ8_t43ƪp4 b k('DŽnpqf.Jѱ0dqBvYgG7.Fq[3,ZECJoYƊSn˦g/."y+MBC8%+]nT;>^.b0};:O1F $tuJC`l7(U:oZr]]2;t{q9d41s|Le$R,j=p3: m]B"#6#Mрj]ĀFC%{SdT¼-$94IՀRhEe 虗 ڣ5`rUvrǮ=ێ [avE%Op&Ǟ*P$ZVk9;OA˗'*>(EdT'Wy2a`#;PT Y\2`YΉ6PE&ՊJs{!]lb7`^ M.Kbǭ$S^ ƿ"uC^ėq:Q"-; ^\RwnNl-lc-f6$G.<@R2 s?`[4Qϑ2o:tH\Uj0 PgY(gBxǎkg kQ5RffN:JEj!yH7g<^l3MS'9 IKz,Y=R=;&[&Rl1_P,(l9m/_XeZœBn~Q9,{=(Jm*DcI LcUU/ocendstream endobj 541 0 obj << /Type /Page /Contents 542 0 R /Resources 540 0 R /MediaBox [0 0 612 792] /Parent 544 0 R >> endobj 543 0 obj << /D [541 0 R /XYZ 72 702 null] >> endobj 46 0 obj << /D [541 0 R /XYZ 72 655.8483 null] >> endobj 540 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 547 0 obj << /Length 1885 /Filter /FlateDecode >> stream xXYoF~ׯPLK./ IڤiRE%J""2Iѿ\KR4&o!윻SzyHynky=ѲUy aB.:H#_/'O^`DO/WEOγٗ7O^]h"9"&//[6q&aO"-{4/>]X`}`xy{֣;`r){˩KMV"%&ysSfک;eF\mlYՌIn%gs5Lϋ,CD3ǾfdZȖv d":6XquQU a.LMƸ;\,Vor#tweK>1^4@W. ٢Sr -< =eYoPdDr{.p˂;hHD"l=rV%g- ,i tr** YJEVϢdwl|kki Cfwav&KyI.D"{6 Xv 0D%z:|nmi2,jyR4D.T BK.Gx%Vȋr Rdjy:r'VNs#u637A<ξCEZRvS=I- >;>`P;tQ64`:>7:hYOj*I N?G8vU#$E ㏒'_ =5В‘lb&a$was=Q(JGc r=Y:20jL2endstream endobj 546 0 obj << /Type /Page /Contents 547 0 R /Resources 545 0 R /MediaBox [0 0 612 792] /Parent 544 0 R >> endobj 548 0 obj << /D [546 0 R /XYZ 72 702 null] >> endobj 545 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 551 0 obj << /Length 2462 /Filter /FlateDecode >> stream xڭrmd@5Sljgreǩ9)1EjHʎʿ_ )!r4W *5TpVwݕJl{a b˄T%#77WoxU\nvE0n_ֿ}dHYh3M1dY'ysy㑞EsVfa\Q?7QfuF/E[*C tjUT?\0l%%ݘfYʤ xk)3wwI!?bB&HGUtw lf떓\I'ϻF !-|UG5D]Pe#J8}憓ڱ*9dyֈOP?bM$I@8^TYnΚgMG̱ۈji4=?T5YlbT!_}cT3?RC}OYM$ǚVuY#AtKMIX)b%r&AR}{Mh%,wDݱ*<6zw|Ăq)8yGw.npıP$ Q<o5V߭to]/qGR;>?xb\٪X2I h!9QQHwś(bk6jR?P==ex'EEu̬r;$ ]rlTyJ1\`]y50Vyf+9ʭL(})Kj$M/`z0tq hf>p;A)C 1L1J :ZY*uyP}ςG6Sbb[nC jI/t}Bd8O0Ҹ@t/,̰ DH_L jnKL-Akj#,\35?6V IduAY!cTHFO!qL<捐]@@`7g LskXU-0$zpq}7:Ip3AlϖX?_^~y0T) RWsR$ *Q_ 0+S#Ύya,"-шs1ét ŸXXh#G '.}hƼ i=5H6}Wʔ(d/n6L Bk: /r! -IlEĶ7xd4+' .mCC4"8^&ckҸ_TtdQ"<h:^:\%{ñ6TBq.Vgdn0. {нw>I.6@su Poo/.$L{gx곉ŏכMM;$.9}Hp˓ 2COT|]|^-  -}oB#rƏ%/;ԫ w3ܹ IjMmAܓlt`_F:lo(gja7mS~ʆQSxR3w-*.n o1^~g9 *ϓw@dY_F,G1568~6Y)h> endobj 552 0 obj << /D [550 0 R /XYZ 72 702 null] >> endobj 50 0 obj << /D [550 0 R /XYZ 72 658.6379 null] >> endobj 549 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 555 0 obj << /Length 582 /Filter /FlateDecode >> stream x}TK0WHW8"-B6=T}҆M*=3 T|3؂p b%\.ϧL'q]1+Da^Dp. QzWvCMDCD8Ǽv\Lk>J1k;ga+EPN*C7y!=\R Ls|ɞ9Y[GLz.M6{̾ub $T9nH[[c<Ӛmlsi韼ݸUa- p!/L6C,G,֯Q}.=-]jO}~r!0-<$9:| :hLt ĸ]PoTO D,b2賙1KIqi+nlHqϰ q*l#UHҡulI3 &]ק& ~]ipINbeYR1$t{oAAOQnKhaUuz*LK[zoxc"8.T JfKkުJˤSw/ {C˿:*:.endstream endobj 554 0 obj << /Type /Page /Contents 555 0 R /Resources 553 0 R /MediaBox [0 0 612 792] /Parent 544 0 R >> endobj 556 0 obj << /D [554 0 R /XYZ 72 702 null] >> endobj 553 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 559 0 obj << /Length 2100 /Filter /FlateDecode >> stream xڭX[~ׯPR@5+/1bA WV%rCQlPqB89sΙ1s ?3t2=ǹ(se&?v\r\}X'׋"M}ՋIR%(-9?zU(|~/Z"/Os/І)h=b+S+MBy I*wIBr/u[ywJ"q fflNq+ܾ.v +fw}dpv5 f6ϒVmywvYKiRvU~aq=0i )OCU=$Hxt;4_-jH^ϰCS~Ɖ\<ڇC۱8_6KPEdwm{/B@ y]j$ʼnqB56 ='JEV/R2zt^3Is2VPV(6Ғ8W:D41{x?Rdx8Z=yDQ RWm)w;uJ|[WU̎h=ˆkN4|E >n%KXIdyڵ7.y#'qv*X`2iqV4.A+(< Q̕ q,} ȃ)@~Ug.Μ);U6}x0`㐙+ YȁgTv|3`KVHfGu\ԥ ljk0)m4 YAO9#˹S@q?:g&eNN]Q^bAVʍ !Sں إIJ $8ѺmHva7_1Q1j-\u+oLY_ؽT"uXjSuUWoϿGȈz`܅y'6soO5$>BY@]<3] W]OM-Oݡn Ry}Al jmlH> /%N㗍',JAa|\rjTȊ R<.ц:Z.yW+.edE&NT_܁LZL]B^¾z!eb15!A80@ZxAk|> x ?9a}ݼ5";4Fz3pS]|Ak3/BEfyՆ}*}/tܿB'SԲG!j$: C+U¥OY XHHL,O.vj1)L.A=K135BpvAD~s~p:(Pp{=UF4Rf)gb>'XFj: BthGjUYLPknOGdFam|2,5x{C;Ÿ*ru, rTt$o|@w$賉 E-7) B/_%jSʛ]5˄cyk6E`ܵ RcGEX©,if0G! > endobj 560 0 obj << /D [558 0 R /XYZ 72 702 null] >> endobj 54 0 obj << /D [558 0 R /XYZ 72 655.8483 null] >> endobj 557 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 563 0 obj << /Length 2367 /Filter /FlateDecode >> stream xYݏ6߿@͈%IHphزĖ\I޽~EIjs}>,pf8Y/b g.6&^`-+ª89 &Z# X\ yN:V>zqS~s^|)Qln=D[ys?g>_LOyʓ$ӣ͕s:oeDU~7m\8t"VZؐxU]xXfyx9xρ/І9RByfWƞd/+fѺq`M4:WTu|\G-DdO5SMߣ`$؄cU+X&5Z &k3Z!sM3[CBK=5穪vF}Zla![*I~/<w*g*X2hHCdWF0u9*Nn䋹 *Npg qX<58Ipbwj`^Vڲ?uaiOqLD4xӣDc08X9 r.m;?Rf,*^{D2HZB %p!b@e O.RvNa \Քp+T <r@WC\4UoNw~K OlfJlf(SWV8wN#[w`Ewov87- ?ےu'n&~*)Tȿ ^ۛ3T!n"}o`'2'3ljhu9D5Gٻ ,.Hl^'VT|k \An:fAf6l#}@H. H9 IyBA mއtFG&oCˁHOagPx=ޫp@yPRn籨]xLWt7^&<8ە"o.@}#eǺa)ƒsQoK98>0{&,_af ra˕$X}CѝDzk5R&xJpC Hc6蓢Yœ߼E^<!2L`4qI&(9J(Ԁkxq O}]AD- L1:S>˯Z` `~Pp3ι|+A*IWU7I"Sn(IL9<:S*cYtkP@i(0Q (FlH ^F' p26S$WNVIq^ڻX.(NBƕtb(6Ffz&g/SMt,Ȑ!Wr9aӎ : SnHk<Ԃl<ԟi<245):ʇC-^u%|ͅ^cN/[~#:%}ib.%fҹ/_~ Oa|%5B +Yt4eʌWNCfih1u}h3~4Z%PmM&pWYnkj48&S&Cehu pj8iz֣AB}b]t'z`ڔ_7DՂI<]GBx+˦r\Q΋#,c!}csP,P zs"B7nm!'.]k@DJgxٸO :sKvj맰K_][EEg* (N?`+(B0'“0c@7e RATsZ (_ VZ_c'4hKC 4/ [M83?ՈJx8KU}>\-4.uB8&SFp1צ_Lfl_eGendstream endobj 562 0 obj << /Type /Page /Contents 563 0 R /Resources 561 0 R /MediaBox [0 0 612 792] /Parent 544 0 R >> endobj 564 0 obj << /D [562 0 R /XYZ 72 702 null] >> endobj 565 0 obj << /D [562 0 R /XYZ 72 544.4977 null] >> endobj 561 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 568 0 obj << /Length 937 /Filter /FlateDecode >> stream x}Vێ6}Wo҃J$H/)6[Ųln I_%LyC~,y^Sͷ0{ %aT0pDy-bQy=|`*gjXBX_LJBނ4ZD;Dd.a&2:t zԤgˮ֟ʅвX*&7m`ESbDR'-d1DZ`P6!> OE)IqA3IxԶ OQ|K> (k؁ũ`ſ xqJ35.\h.!:vq8ip ?%8pzcIo@u،>fǷ^# ^?p.HPF{<'&D1m;; Ҷ0k6rx Ƴ=v(p0^! p-#ZĔ q[14Q54b6X0\][4Z .\J@A!냌J=k鱳#%LJhVׯ0rTHTjM(8ݔr>c7`_j_BW e(mQ07=A?65n0mB4c<O>Eb 1b~|"c:%G^jӎ=9xp.|#HIo]d!fIqOy(MūQަsXag͟mX]pרS׬t<f|{S2&X^)oR$18x3fRc˛:๧c|t4p]Dr)b_?Wd2UM>ΰBZU~N1 U9:R۟;Hendstream endobj 567 0 obj << /Type /Page /Contents 568 0 R /Resources 566 0 R /MediaBox [0 0 612 792] /Parent 571 0 R >> endobj 569 0 obj << /D [567 0 R /XYZ 72 702 null] >> endobj 570 0 obj << /D [567 0 R /XYZ 72 655.8483 null] >> endobj 566 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 574 0 obj << /Length 1921 /Filter /FlateDecode >> stream xYmF_J$i_JIoII(iSC(I>l,b;C|gvVo|qv5;;;/3x$Q\w@(K %Vn *Il'\|}:{!UW2eU :Q9J~4XRڠӾZ)[)eYp۷E$eҪp&nʪ<̖}ܩ8Sp{cW45 b&R2,Gh `PZx ўE\15&eJũ;Ż(Ua&Γ< KٝiE?Lk8"p,[h\"t^4xٙ|c?CpGΡPWHX/h9T&7 !B9N{]xΎ%Ί'C#pWD qDg:e5jE†嶢 0E4v+66C2k: lһoo<S͛ExSfUl*(3k7ekK}t?JP%'NzfJ+a1  3zۅ>燅#S}4P82,VgނjHuѺtKZU@mlpJFq{A'䷃2i``9`P!MY ])$w |`Ec?֝**\RZ28̥/]r{E~k]bo(J',29^xwBl8Grfej*S ؼAlBjF6׍ACPwu? 6ȯ?<}9=)Cu_LQ_=6P1'c$Lij/ƱUsS*xo 앿\M;Ebs%SlW~wCK}HqaםC%_0wzNU vv]ӳ' '8`\/.Vwtvg\D@o ?py} ϏµvAr뛦֩}2כN QWM۷ n ukf_/Զﻨ="V~'C.C|)VnOdn0.s1SXDϸz\ . @O\OR}h*gDOrޣa:H5u,m|JicI.2YBHLpe s]#,.^8pk0t>5_Uxy$L_U9tC弽==N v͗fk/Q/',}n1 kLVO˖'$if&;[Eƣh =k{ϋJTB2!8%ƵyU+w44$ǻo,ۛ7E ҴVkQ=ցE /Ҿ#1ׄCaz16h+I^5?Bi \*ӟ5y4LA@L=Px'F/~p& KOWG m(kAh /gs}ND[tS*B 8yz뇩W~cԞGVK_G TWS/\5k8VCYsԻ^*b}^ODUh_s.yɊPsqp^Ryf;[lgõ=`=kȖcz6Y;ϊURZ%5!Z?c*+{كhRWtBZ[6#0fzˤJJBklMM](HlRۓZxYܒ!RQp!POnendstream endobj 573 0 obj << /Type /Page /Contents 574 0 R /Resources 572 0 R /MediaBox [0 0 612 792] /Parent 571 0 R >> endobj 575 0 obj << /D [573 0 R /XYZ 72 702 null] >> endobj 58 0 obj << /D [573 0 R /XYZ 72 655.8483 null] >> endobj 572 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 578 0 obj << /Length 1868 /Filter /FlateDecode >> stream xڥXK6WR@V\R"H -!Akkmwein]w,"<< ?%[f[Li!c򚈁 >$2Z.*))2)oqçXjmmLЩ@&rFϋ4YStO:Ic6(y_̳ﻺe{Y!9o[VgR,IHfif:Nݤ}>0eTI`um6# wSQA FH<0!)pFFn}.Bi~;2(8΄2{*8t@H0LH~*(070h 8+abLz )u@/QDꌱQ FrnFH8o*$Bψ=TpHXQغ b۲eɱ0lS=8 ҫ/u5wyBy5//vZp̺&*,>"rZ([U 2"YL;"16~fFGwݱ$uόpxGJ9ZtFmc8S* z)X @5&Su6p`aKJD -W)uz H#KOT'q|~v)VլTf"Q|*@^ߜzyuXGz *mV5 N$i_Q4WmÕa)o ǚxLS_|wS269`O` cޣ~,ƪmbu‘;;*k2u*@A=EV4XQ|G"g;v(gqv<4`GW_h D([^j#/\y5ep܂ z*}Сm"XgqbY?ro =⍌HL[^N2%1 9urʗMendstream endobj 577 0 obj << /Type /Page /Contents 578 0 R /Resources 576 0 R /MediaBox [0 0 612 792] /Parent 571 0 R >> endobj 579 0 obj << /D [577 0 R /XYZ 72 702 null] >> endobj 576 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 582 0 obj << /Length 1591 /Filter /FlateDecode >> stream xڕX4޿"|K;΋7mҘb"}ϗ  VEl`ە$,eIk,r3_ ""GoW< xTxS,r>|}\{)Sd)Dȱn9SL '];()KVkrix\i)e8t:yR%cg2Ɓ-L5hfLepA„*U[ȼtfn(QL qE\T62QƊwCg=ĥe(̆OQ*/hsMkXޮ#4Ɋ̓$E^|2@Zػ &4 k`ꑔao04(R/V+@}=;l+"lO0W7ZwO9IMt,C7[5_In߸cR*f ^<l1OY&0m謭FQ,!C?*7Mx Ilf@B몍Ld)I25VAk}XhׁZum[dzHLϞ;" RpUDWmwlzTTG͖/!< T&I^{sxEĹ?B[r!0M]}8ts-yR|}##ۧzXmCVq.Eiy}={"H+T89lFPP#պ@FzlU 03tœ 0S[8ε!bk.V" Ǿvf[It+y],w A]Gp\=`yK'q+&T9Ƹ|3$g34 ]̋2e*|H$Ɲ(Ncc4bD1"V7$3x\uOoT6a#RԎrJ ]]˿wuSP?l{/i[7'};%XQS4D7xLUZ;`#u7*IT yG r3Ne{::ϵjzmeШL5ibfhҁ hFjZP"r]쒦6c:Msw(o}‘q ?֟quPYQWk"}d5d/y~:Y Iݸ^ě$UJP鹷u SKP ̕RLj$=j4"TFSk% n_Z89bЂv6Q mH ^ (ۺQ'n{p${ii0?tݶnl "J5#w?=^E2)z00 6SDžUn|Et+Oͪf۷b<A(ckg&)jsh,Gۇ+ (vD Pr d`$J30Wʒ%97>X5K?K!SdH*/4jFy%sX@^ &pҕ{Oc!endstream endobj 581 0 obj << /Type /Page /Contents 582 0 R /Resources 580 0 R /MediaBox [0 0 612 792] /Parent 571 0 R >> endobj 583 0 obj << /D [581 0 R /XYZ 72 702 null] >> endobj 62 0 obj << /D [581 0 R /XYZ 72 658.6379 null] >> endobj 580 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 586 0 obj << /Length 256 /Filter /FlateDecode >> stream xmN0 y Cqs ôuMiI26TEQb/ `F#(Gc%ĶFA3 H@k!o6-(z6WpV]3wϖ=E@eNS ! ?|A.#T% "݀} vͽa&M"E39+0a4_`y;K m}u\=׆1hyy%UnzESئ owO[*/iendstream endobj 585 0 obj << /Type /Page /Contents 586 0 R /Resources 584 0 R /MediaBox [0 0 612 792] /Parent 571 0 R >> endobj 587 0 obj << /D [585 0 R /XYZ 72 702 null] >> endobj 584 0 obj << /Font << /F32 324 0 R /F15 309 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 590 0 obj << /Length 1777 /Filter /FlateDecode >> stream xڥXݏ6 _pV%K> E6}'1jǩc8>CQr$~"OāqRqfo XVGffaGշW$C7]Ww{dX5# j䨋MwEuoIaMkF!8Rpḽkރ w+pJEڣR%pS_^*{p%lAmwLt-Snp' _~6ʮGo2=N,BJD[4rn%$ܐP1S)Ep(-H/@g HoЃR+K iA!̈ ј cSJrРOS]dHPjt@{vH YW Ŵ!O\!4K`luWBZ}BOgm+θG3M[}ke*C61)Q&cdOF1M^XĐNG.֍"Q <+[Ѝ3ct+`RW?.le/MASĜ,53"x,0<+k1$O0Gy$Oc}uE #Õ2`nWc:\-S:ym~C}nޮu]suwwߤoӠw7˥{oKw52=uR,>G[`tUZl-ǂ{@Mm 1#Ȟޣ =: S%[ UX吹v;SnM@$8+N֢jPT7ZUtngחL$(Kґ>萔^;}W_aoCqQ&An73;"+n u )#WGW?jBPK5ƛ8>mr UZAÑ%I2Fy @1B0HL`ݙ#5_?`"_pHTw8OAMRQ/$WFj~HPI.q>=DeP0jZi.)~th H{P~C",̤HpYܶ?W]> endobj 591 0 obj << /D [589 0 R /XYZ 72 702 null] >> endobj 592 0 obj << /D [589 0 R /XYZ 72 680.3998 null] >> endobj 66 0 obj << /D [589 0 R /XYZ 72 680.3998 null] >> endobj 70 0 obj << /D [589 0 R /XYZ 72 294.824 null] >> endobj 588 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F31 314 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 595 0 obj << /Length 2578 /Filter /FlateDecode >> stream xk })@!o\r".p I %+%?yQ>g }΋zRIdRJˊd3ki=BP# P Go_j7*-U'7K>E n$N͆@>|VN+B\&}Z楟 O:'yc ┦7wSkkÉ~fwojR+ ?JM*}Wom#ߖ OkR9K3,&Uz 6 <Z?ߖ , oIUV0sz 5,-r.} pIwdxC2¦ᒚ.x,8e#⾞,Ot1J^3ig=v>-&s)ԔɁ3kmꤛΌOt8|1̞BN_wl< o}Μ!>M2{PNag+q\ut!sE'Xܖw`P7뺯A !U$n`iwBA#,Xw9mgZkre8u pE`Nؤu/k7|ʩwx7A@ڂܠ5g|ݡ"?N{Mgkmeje`2(>}Ѷn`GetjU `8RZP5OAQO2[q#Dnmv{Y:āEpD_5ȿsSU9VWv:gOskAYy( E 㾶gE2Eu<ùF>>K_׷zǜk8:[:$>Nb(,4Vܐfx5{N^٢w nF WGI[VSPwLO4߁Rϔza'DthLaaͮC˞8W&OvTsY315EvfK=fbk)DARU -#;;AZUp ENݯ#l ad2ggGj#ޢАH/} p N ʏ.Y1?!IYVwJ.kL+_ oaERA 3#cǖ eϓxsCJBG /A`TI& KmQ>FEVD%FˊO2a7e#F] 7zݒ1E"1. $GldY"V x:{:و:>2z]04<0>Dܐ.PblW  ߉  h))) EKA 7v_ƄTj'Bͫ pAg.pHEf|e*%S>=Ϫ +%kʍrO'$ :pm'vڪgX alAnXNo!K}.4+T4CIa CbfLe޺tx1UL<3C!bK#]~a'%VUk%C%9Ct @x3q|M[r؅a:f%\\9?Dž 8;k8.yF[P᣺*2}^xG-v9u:a4x* i~5Q <* !<"x.m Vcr 6 ۜ)88$T>XGI04+zNpO`=;UZ-cݳ#62irŢȵnjE#BPM6Z *v GYD1?!Hj \p\*x.F݉7 Z4!tC.IM| BI#o@3瑙D`R<,\v;8{Mĝ(sA24^_Og8 ;B[q_캿p/u8`3c("L}/Ya|^AGrra`G6C/apP2"j'=:@[׻L%$qOÇ)[K@:T|ۜKv@ޚ|S֛?[8a yC Pzb#ޖzF;wLDhY gM%>W89@Tj[VIP#|> tR*:,xqM!MRUf2+> endobj 596 0 obj << /D [594 0 R /XYZ 72 702 null] >> endobj 74 0 obj << /D [594 0 R /XYZ 72 252.0728 null] >> endobj 593 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 600 0 obj << /Length 1779 /Filter /FlateDecode >> stream xڝXIs6WJK -4I$X$6Hv=V<|(!e-0Zp_®Kx-H`E>q>0?]-.ފx) sڰ*>yW_~x+*S9D%"?_ f,ȓ<[-uwH96ҩOnV2L{S]TQY|. " <͖'AgrPIA/*Ue1:BC'I;yTƓ h/8~WvRDyD(X#&H8]׹uߛg;sGM3-u瘝v4/GGGyM4ٯ|ၖUy=&[;Upz*xԯװ`o6-L궬nSue5t(o/Q w4ǖͶW T]sɧu=#65f`'Yɿ}3JD=/bE `SeЧe3TVk}oZSzk5*!qq vyB6elsqv1RfWW9Y5ipC"PB{H|?A'1KEc"}яP~,wݚ)wv qW%=- J))i6 s}ĬwhKNt&Ԃ8J0 Rw%up˘gmkvʛeXXn;ޢ= m;$¤qp92K;0)/-qI3uTOLrwsP1y}:Tᡥ{NƞCom[o/*VgA'GuTMj;;7:;|;ʦKWh|yy+jGO2&> F"agK(d<0@` He[,Vi ]Y[;d]neTorM"}e]=%y08_08cukn#!b/B=:|7Lʻʽ;p'+^'f#p%_Q9xfbqX$ %` ȽmLwv]XKkƛ´v qj}!hZ™z6%Ψ}`ɦ5ӚzmJ(%R|яZoڠ6'|PХg֕G"O[{&!~`/s,̪x 7,b>{JbAga;/ـ Xgd S: T~4"7S !%t?ZR 26^<"׼?@Q<^HKwNOUvճ劎:B&Y$c8"[$b.}9~dU)AZ9{qdԞnz I'_}QA,D>9{ay _Gh0:B_,!do(!)i?%CƇLc9ɓB0[V;8H4X92NHDκ 2V\.C,endstream endobj 599 0 obj << /Type /Page /Contents 600 0 R /Resources 598 0 R /MediaBox [0 0 612 792] /Parent 597 0 R >> endobj 601 0 obj << /D [599 0 R /XYZ 72 702 null] >> endobj 78 0 obj << /D [599 0 R /XYZ 72 459.9994 null] >> endobj 598 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 604 0 obj << /Length 1321 /Filter /FlateDecode >> stream xڥ]o6+\YXS$,6: VߵpbeL%Ԋ!@D

bΧtp饄b2 ]z7ﻨT"qw]ĘAFM;I7hW-k0w7mPo~_bPj&{l 5F /vY)"%4 pViȲ+&|8z{vF F1xA]zɩZB\زɩ\~|e=> endobj 605 0 obj << /D [603 0 R /XYZ 72 702 null] >> endobj 82 0 obj << /D [603 0 R /XYZ 72 481.5734 null] >> endobj 602 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 608 0 obj << /Length 1468 /Filter /FlateDecode >> stream xڥK6FZ 3$EJbvѢ)-NWIWA}IiKEm}ѹHDʪZn'je"[xoT7lcݟ17?>L޼nD8P޼ uLu}.1at3*HJyBSlPˬ_S?~TL>~M8ӦW3i:Sm'‡ɇq?Z2aMcRD5qSŎF5sn੓Y':YCz0zƾ6ZΈ74Ċ0TRO9$Ը#P!Vt1"[$eZc0T(+JR(RIH=?zI ͤRy d%)`L$.\~6-:u=5w [oogae) ^jbPXR׃uh-m sd{[ZRm@DyX<$p,5_Wn+JD/ҭSc0@)ĊeL))Vs?7K1]T:`\ TMBX kR@e܃ruTvv>`aw7ԖO>gn'# b1D B06AJER}~U\r!:J$pEohαmY |1Ċ0:TROnwت>Tw)I(+RRUH]wsNQs'VCHbJE!u7t۵{1v%aCvSYmJZcT-8V뎚 uwcw68}d%)`L$?e$RJ2Ċ0JTDR}= S]?0@XєFӔBv1\ܒp"tkÔ$ nu)`M. [ׁ7ԌvJ*Z( GsnB3.](`K nsTu7 ~cGG;jzXI\)oM_'lVpwZLRBX02"¯rn}MDw2Ċ0ZTRA)4RP~!V/"~z,U-IM0@yXѓFϔxBv=N'`;!R%O6jȼ%D>}N-Uw` !)q5䷜dcRd%)`L$*jsꮶ_·=:;  bRXRWܳ9׏D~V&WӌO{ۧJlЕp@R2%U}}45!zCe45/^nofnkmnM@eZJxGbendstream endobj 607 0 obj << /Type /Page /Contents 608 0 R /Resources 606 0 R /MediaBox [0 0 612 792] /Parent 597 0 R >> endobj 609 0 obj << /D [607 0 R /XYZ 72 702 null] >> endobj 606 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 612 0 obj << /Length 1256 /Filter /FlateDecode >> stream xڝ]oE+Vv#Oj*H|)$PRHڞ眑\$gw]dQCCzzooWEVHoq1qǚ]lSr"ɤݯG)~ؼݽ<a, EaMycX}01S ]򶄖1l0_7Fj+a>T[9\g˕.8|)Xܮ~Z0l¹L,0V}TԬ(L~bd딌*o,%u~S:8^^_!EzDL*Ђ XWVJB/&yw1lu8:qɻ6yz٪ғK^V!{)N=-xO3HJ:Z8qR =Hbz`2pz%Uz?JS 8qR =H=DWb]=XZ*0=X2hNĺzTBRp&1P2J[TH + x\%-Z*Q~65i=0JLSW *XP*Q߽xzWb]?XZ*~gǏ1?_=`+~-ԋ aUg p~%կOH3y>8qRSKad pz%UGRᒯCpNĺzTA{ԚFFoXषz3ӧ_HMJ_K% 4 =\`+~-6[CX:-\βĺZ.T͘$Nĺz->?$;0 3@+ĺpZ5I{fWb]=XT\R= B 0L^,p*`AŧԌ%~ǯsQGzWAu+JTg 7zʁ\TןUI.µ "wm~u9`- @#R^!WBE @ĺpZAK%*V`FY*(nVR ^Aȧ:.2P t6!Uo=ʔt`~K#eO.{Z 9|}1f*/?7:?\ޞv;'ɂ?eH=ЍitVb]~jRendstream endobj 611 0 obj << /Type /Page /Contents 612 0 R /Resources 610 0 R /MediaBox [0 0 612 792] /Parent 597 0 R >> endobj 613 0 obj << /D [611 0 R /XYZ 72 702 null] >> endobj 610 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F42 469 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 616 0 obj << /Length 1951 /Filter /FlateDecode >> stream xڥXK6W"%14HZ(F{HrZ[$f;R z(XSpH"HO DfG~#܉ ]9Jny^@QyIço>iM $"Hy$\ǩ̏I4ga@Hep?ݚ4UVl 2Vyv}'RHysEqfF%V*V*V"IH=a`+A=!U0ѡkvO[rpxd6/B g{`A;EĐH D+Ve#*TX A==֨^D;x 5mH&Ҷzd IF2) K>]T^î9W5#hZH:E)/?Y+#1ΝF^FUcOhjo)r>HADxȀxhm=Pn,/e^C?g69e{b<9W-)NG0k D2ifH:v+MȾ}0eClQ1Q&ܝn-5ac>өq&{vU] s5 1׮e IBJCI;7-9l.v#?HQ.{ .7ql|!8(aۻLЭy@߷si8;0}#,Pi띄ei4W{ۿ3ٹ{ī`yqd̅::Z#hl wy g$zxκ%r 09'qO&r ܹCF")q鉬kgxᩤ%X}0i0NKh%d UӎMiC0E5kT^+"Q]c3$Vkv)bFL͈.refѦI*\LH]oa) ʰYtZ](dq:suR8c ]rKQR/ z佚,:^qSS)ДHKi_b%5P::uG)PeGk '*)wK8P'鋕~ } `j.7%pX/*H/*93aveHOy\Z/ 9 ,!gv3&.ҙP9!}vX]=Ӱ}r^gMhzd} #f{qY]o,w Ad] 5K{܏r \%Ck7VwX~s] h:U/^ƾ~6 qwqs \籌/phOF$Ayēe$^Bޤ{Sr, @V-mIXWM5Vn\Kg2TMs0v@> endobj 617 0 obj << /D [615 0 R /XYZ 72 702 null] >> endobj 86 0 obj << /D [615 0 R /XYZ 72 680.3998 null] >> endobj 90 0 obj << /D [615 0 R /XYZ 72 178.9628 null] >> endobj 614 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F31 314 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 620 0 obj << /Length 1932 /Filter /FlateDecode >> stream xYo6_7=Ztv{ AXMpHYRd{tEf g,2"s2s\f݂g0Biƭ.hY"~:ѭq}0s/{)n7_-˷J 'R)byl(i*G(U&cnJ/O<x*yM^68qӯؼrR Ty4?Ƴ (Â3] >--K=ZAsf qdgZsELP0z2W)tO^B2{%0:tH´V*YZkIRy߅ p̿R~K|(kPi{&n#5iuԥـ43ba lȮ Rp(P*-m0]]FdJKs%U. <0z zC7E(ȝw8,΂2 J" %'PRπ2'A[o&m#!x%7ⷒ9aKHm7q+}|> B:v\r[(j%~ZCKC;`4b<.q[W4-&qgN{?8Q7y *_i*I y!V8_R1_i0uEА&bM`&CE]OͮD^pFmkFǤPh/X'<"۔_e\-O$kgGv׽{UodoNА*HiϥgcL0SvO1 >`K7.xL8(av 0MlAм\78 K3WX%z<8.N37,ovTglv*ݞprӱ A#]N'6(@s ҴtY4 홑49y4Mi64 pK4C*Vbǒ$EW0pLZe!69D]S5H1~Bi=_L8#+]E4;ë[>znSCؖMHLقIn?y[OfM 3(WD4 xfs,_;0'L)І*C\bhGDiemihWhSӞQ~1~8\Ꝿ?1 ,ZX:SRT*;yM1,Ǎ)qm/čԐ1 AaM*R].>C},]cIxf% }B 0.Bjy ՞n56P EV}\5&6G,_@ugJS{+O-(tvQ6r7IJT+*S?*cC>h6J׻ ?cVKj4mh#BZEЇזv[h/4xqlrSJJGrz4 X*4e7iRߩ}|vƩW}CḏcɌ{}2l4IǾ96'z= 7]2e%tJz`~⨽AK3#D1aBUZ _ҏ]e][!.Ԡv[E_'%T#ϊ`V4 uƽ!&G C2g#-\G9O "2S(&X5cendstream endobj 619 0 obj << /Type /Page /Contents 620 0 R /Resources 618 0 R /MediaBox [0 0 612 792] /Parent 622 0 R >> endobj 621 0 obj << /D [619 0 R /XYZ 72 702 null] >> endobj 94 0 obj << /D [619 0 R /XYZ 72 508.8164 null] >> endobj 98 0 obj << /D [619 0 R /XYZ 72 153.7017 null] >> endobj 618 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 625 0 obj << /Length 1589 /Filter /FlateDecode >> stream xڥXnF}WOkY 薠(-4#pQDJlmH>(NLm:z@M8p|pV"8I#U8nnˀ^m d!+]^UwYYj E/)FkcY2ϰd80\5"ا E  #3j ~a@-az.`\\/X=}W0h@"o4]访4 Emd00X(j+++6@ nkevXަ.e]0;{+2;"sV(IZwݕ7Vj=ֺ C}8)?@}Ap6uWc]krno2cKM~lj$Jy[yhjk `M.b9T/v>>' Q."5i*hi*쒒)EhϦ+4H a> 6ᘸ%)e&۾ɾUޢl95׷ Ȋ $/M KMT^$9xl찳~hdY+B^J❞l7K6[qITĽ4Z|j6 p!pw|Abt]L*%z0:11CJ|83PX,Pj7T]͔J$ 1,̲#,Q.hjE@dCQŸz.endstream endobj 624 0 obj << /Type /Page /Contents 625 0 R /Resources 623 0 R /MediaBox [0 0 612 792] /Parent 622 0 R >> endobj 626 0 obj << /D [624 0 R /XYZ 72 702 null] >> endobj 623 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 629 0 obj << /Length 1120 /Filter /FlateDecode >> stream xڅWێ6}WQ"7]" )C6\K^V~}gxme/XI9rf ,xQ;<HBS1Cy4bpg4?w߱$`(X?Z_ 9DROD|HD*L%|=B̩DW*]j >(WEGPgnq$ uW(f}_~ryF$Fv_ҠQ,‚rw2Gmc̄'e0IL A*"%Uf]=!$"m&Hd}EnJ_x9Qg8dlx/! -"~=;7'篽$ 9 ~uߣD2ܞ݌< JHO0k T.k\o6@Js2ylnD(N~P;K Bzκ Rg<_2|rJi.]n:Bm ^}2zpjNV#ow4EM몟@y%&x%Jᚍ߈G[lc֔ۡS5 }\6}65³k&8ȁ6. =Iokp1f>/5!Lna/ ~pR|zE9qeGP;P#߆ץ)l1~Tψbŧ:4S(!PpWYǔ-iCm[U7`42+HnFlCr:c5cKK 1d͢5U )&H"o)+Dau (V)I˜n=Δ)Δb;SLILSnp0/@K&oNry*8;\(g+%Ywe[EǕq.aoh?Vendstream endobj 628 0 obj << /Type /Page /Contents 629 0 R /Resources 627 0 R /MediaBox [0 0 612 792] /Parent 622 0 R >> endobj 630 0 obj << /D [628 0 R /XYZ 72 702 null] >> endobj 102 0 obj << /D [628 0 R /XYZ 72 655.8483 null] >> endobj 627 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 633 0 obj << /Length 1396 /Filter /FlateDecode >> stream xڍWK6 W(D\>%=dIߒ[V+[v ,۲@D'B&zaG%ldF$ R?w?Ŭ.duGYnJ67z@Ub,+ Sz(gF{`ըI)kyªD0kI*LqKeF)fK"?t&ɤeBLFL "@zOox n{?BK4·cʾ?$D9\^~6Rb$e 9g).X)FХдBZE\"ݞ-IW! O@gNF¿zǍKPudzD la^ O+ OTHv1=\r 0&vj YyZWYH!9 O"ERxɹ+>j*XTe] 4D[mlA۰qH|,{T{Z% (z2e4$~chvf,R@ QUK2͡j8M7iN7tu>NQqA mLaCƊH,VuD;'lngzR!Ou+=݈FƲngZy<UWA*P?쳹yش# q=hG:r >·Q-nr5S/ldA%,NjTj^3FWZO争52Q|!4A&NGHl.5P^DxgS4}8FaYŻx|\RWMM 3 ^h߷\ $#mOkSA ۰neZG㵞NP{?Zd 4h“b0|a-4|rȓxo'&*y/-0n?Qi,>.8Py.ĕr:1o7P&) XR M=sj6@g20 JX4)NTʈQ*ϩ.O> endobj 634 0 obj << /D [632 0 R /XYZ 72 702 null] >> endobj 106 0 obj << /D [632 0 R /XYZ 72 680.3998 null] >> endobj 110 0 obj << /D [632 0 R /XYZ 72 231.5296 null] >> endobj 631 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F31 314 0 R /F32 324 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 637 0 obj << /Length 1883 /Filter /FlateDecode >> stream xڝXێ6}Wo2kś.-M")}pk5l$w.,ٲL:~byy&` 1ChA?%XFA؃ݼf.? 1g-q]y/7ob_:xO80CM&/L 8jlM.cdu Ufu0߂7Iϟ!e'r=?grM2_GFRIu:AX:HŚ ]0ZonK#7W]6֌`2G& !I4IJCSWvID9RǺ"ЁN]$d<֚2s" t{ #ڼq\vC!ϏȠn_yq#xʋ{ie$ ֶcи3r;a DHb˺;x`d:ܦhaueepZK/s*6eϛtgϑ8[nk^vMkp'@H&@6..pm'o pM.񏵞!Pk(!O+Zb&b[QaJj9i⳱1 \, Q`?fDLP9ŘY+s.5m4[6Nqe6MgNO}{e_ŸL1+ d g_K4s4@cgh6G/C[yRy_v>qC`דeF:ZA KT학 CvmP62:bj-O#~AK4|ٷ-fV$ng'/ ЭZiA9&̼I@ gʟK 9z?CKPAZhŏA4D #m_ m%? 戧%g=ԃT0M<+R){bK;ܟK4bX?g9)]P)Ot}#, apQaπ i찤!y-u҆_z4~:={3B7ήoEX팗x[ejsFǕ.^Txg^cw zW#R R)(-}Oq/ĥ 2V{,A;,". p.sTp+J{MIG_3npDGfJ>isUbmd7dG:uzF|,>)O,FyW'#W]rDY3F"e Gnswc[t[vܲol!'BJ `~M$ + - 6w6I="B S 17@Lwvgo{d^}LCBKSx=qX֭X丰#"HJن2}qۼM5TOD2٭#H`? $ YF",=ښoWbZ[1X~˔?5;,W.%ApєDeiWɱ+|/?΍Bendstream endobj 636 0 obj << /Type /Page /Contents 637 0 R /Resources 635 0 R /MediaBox [0 0 612 792] /Parent 622 0 R >> endobj 638 0 obj << /D [636 0 R /XYZ 72 702 null] >> endobj 114 0 obj << /D [636 0 R /XYZ 72 209.3746 null] >> endobj 635 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 641 0 obj << /Length 1167 /Filter /FlateDecode >> stream xڭWMs6W(ML~4id):"mqB I%t߻(RgڱGX%(<‹q魷Cϻ#S*1BGcyx؁ZL oqGX"[N_VoL*#bf-, tJw|š ^u: 9]LqiBy\q/?L8I{_3ĉ0v0(`J+dZ : `5 S'f t0RO|]uNc a=Ů_"F*X]Y[^KjzI*Ǘ2aYnA0m731VvxZ ue3BMsZLɭCu&#c:Ԭ\KM tFN6m!%6mf1 J*S 8lDi'r؏8GҤ7f2 (lRG1qn;6ژAMƉ\b` H[χm`Y%hN̎>Bvtف9weͅ V4Ɨ5ʦI\̙mD#/m $o!0conn e8_VTP&/qmeC#Tb ()Q0:( ƧZNH;D$?D?lWYG_l6i>|xj9+5|(1 WNR[S)<q|C-"0j' ƫ+jc%{HW)醑4bNaq {9]FDž.ݱq N~qCƫ  Kij kJQwjq$<,*{ΰhݤegl쪮"q>Ƌzϓ$ax7> endobj 642 0 obj << /D [640 0 R /XYZ 72 702 null] >> endobj 118 0 obj << /D [640 0 R /XYZ 72 571.1147 null] >> endobj 639 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 645 0 obj << /Length 1063 /Filter /FlateDecode >> stream xڍV]6}W$$@NLdvd 8k^ħY'Ã>8ܫ+!(W3,d@P(D4\e ߃l7; 6yz<ܼl6an0Ӝہ.x>(Ks[T}OЎ ʂ~V0 YAj}%$ڮu}0@d}t|FTWQaM77+bpYw#^((tK\(.;I^;)@ЙƝc%tIX?cWN(DK{Q$*cW"#_7_ IBђq$:NZ+<'^_+}ɳ%:VP@ ph v-h 1E9<%f<[t&$ BPaV8t6aE9tLjsYvPucs_o8ˈe"tD$sln :ѡyTˉ^m;iU]z[_RFb.C]: BA>Y::,UdN?$n9&-ɓ:itj{aK%1WOŐB^+ʆ,QziG_60-ӍwD^/IkrI,L/X|HRDg!Xm'iE}5e&T4E`rt`5#y4]*ywUmE=#Rad )Ͷ6(z _C? UBq-ؗq3<'qxpqkxXdKw(I]Fک!Xtu\5jH]"sӵ-lmQ}BfkUOL#tkh5 KwT!L<}{X  #W9G%wmv(h% FN<\3endstream endobj 644 0 obj << /Type /Page /Contents 645 0 R /Resources 643 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 646 0 obj << /D [644 0 R /XYZ 72 702 null] >> endobj 643 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 650 0 obj << /Length 1325 /Filter /FlateDecode >> stream xڕWn6}Wytkڢ)EQ[6,ʒ+Qw$Vb^s!uQ'fNLȯ jg# 4h[v>c ?-4t( RRg6(bzt?zOO\%HD >-,$ (McS~ot·c iǙ{hO5t[<>g$8q^C&[(;_3Ald*."fEi I5_ٶukYԕq0lp7EN8 &#p/=#LQ"v`"P ˶6Sv25epaʰ7x F"0hqV5zz}rYe֝zw䛮Ĩ1 P"e:(ڹ`,uW, `4/Y>`䦳h_PƳԔ00GŎQ,:L 8]LUn6YLX.ᖂ|" C'LXqx|n}o[Nj*$Sdq{ Bln:1c4?dr/BّUwtvRܮ¸.2:uYKt]׏ފI1aص eY3aAh,>ޏ``y$8PsC}o.c, ,UԻ3X3pf|8/]^X,on뮴gwb6#>cB2C7̬^@hI\=oZ妅Z0B){n:(^\BlzUj-֎=Va^:ʋ|͠jkEF: ZY[H5sC? w? OG SYwTf͆o}䵋$(#A&a$l0{U^Me3rߩ^vja73M s(y Jޜ+X{f ÔTޖK})7%K +v^X !K6SuUZZ3`D V'v](Lc1hLF^ PC101#\MceGM>q9ngM@`E4}e7D\Gu =oWA]&ij-Di&$d0"$L?C%tMelŸ>DR?{_g%¨y,4ǒLKa /:Qz]iiyf`ۗ[N~_A(bk;YZ[qG3GG4蛉ZiMendstream endobj 649 0 obj << /Type /Page /Contents 650 0 R /Resources 648 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 651 0 obj << /D [649 0 R /XYZ 72 702 null] >> endobj 122 0 obj << /D [649 0 R /XYZ 72 655.8483 null] >> endobj 648 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 654 0 obj << /Length 1504 /Filter /FlateDecode >> stream xڕWK6W9@%wAZ4EmLjeɕ8 eilЁqrO:rbF~^H3#q@qy KD<\-~#L: k1}])Ǡ0FjP~g3gA|`*OcLYi|({K?\V8k~!(KR?WY9EZ|Z> Z0G? RWh,n:qa(2"}u"cϝ~W[-knu6g;gh%(dGaHx}in}U, 'Acgc6Ҫl,?0իW y+.c[|-/T)qT'2&^Xza ғn)] ;蚥R(-p2?ƒc0͔Nʢ+4dzpaB R6g75n :됭nS{舷݋OŒ(wtT")d*iuGAx'#x@5,HF}q]'TV@s;KjZ?6sŰg/t0?="㣼^OBf/.M6:bX5UDKǪ`DwyI?)h)G~jT+38 ҏśkV=lL"k喒f` )@,9J셍k!VKN0+IA2;܂iAMV2UZ3 7 f5$d Gs%'t %s #ĸ0of(^,ו]e0K 34q>F:n On2Xl0@C5`A|@C4s|QO䛗I ˖!C0apTry i/if58vƋvډswVěZ~wsS-Fq)M 1} +POc#v#j@x}2i%[ݰqEYfyB~$e6ضx^ Fy)2p%L7|%nh3V;m} Y;Ta`owK'^fR28Ǽ2b' ( )ɜ J|%]_e#endstream endobj 653 0 obj << /Type /Page /Contents 654 0 R /Resources 652 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 655 0 obj << /D [653 0 R /XYZ 72 702 null] >> endobj 126 0 obj << /D [653 0 R /XYZ 72 195.3643 null] >> endobj 652 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 658 0 obj << /Length 1268 /Filter /FlateDecode >> stream xڕWn6}WQF )Q7$n m ƦmueɕFCʒLY0Gp82yi46qBIQ-~"Hi҃Yn?c4gbV bzϟo?D|x:A!f-z3YF$ϼ)DTLC%a4fuӈyvj\gPV`㌒8O3>( ,v3d1׃z~̩sbyIiIU70ut L 3!x.EBU ڶؘNQQ͏O(vuo`yj8n Mact|WrT@- ; 'OPcmA30b[ "[Ђ3PP M슺2zPڊy/O[ }VyT@RaF1$:8IÀ< L +jQ]BCK]ƴJEcFK?7:9bpպnNMc4δ Rtb޽#j`xο_t,:MYtM]LM:f5!(7r-Y- x.k D)^Yʇco3?.I 0s8Ϡ6:̿Q2LSآz׭F~N=Ck;%NAXK#T , !u(?ۢڔV1lqH:Oz+uTL-fElUJN1T)QnwMfkO݋;)BM׺V/]y]U*nz7nl:on5y؊j#'ܛU J_f@P@^G k*7URKv>v|)ЍKO,jNpi Ů5)=@FhQ zN  XPLQ=8ݏF뷳gˡI4ϓ?$M44pI9z灟yߔn窎_H',t}jԎPަq'R(NIBk+s endstream endobj 657 0 obj << /Type /Page /Contents 658 0 R /Resources 656 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 659 0 obj << /D [657 0 R /XYZ 72 702 null] >> endobj 656 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 662 0 obj << /Length 497 /Filter /FlateDecode >> stream x}Mo0 9X$ E l:|K}pm ؛迟l^E}09I< 7@BrmO \R$J`I^%iWYzx 7=}I'cU֐Ss]TJFq1wm[w.>gO7d@JV6@5#TfܼDS1`>jAQ$TJ}`)"ةX9{|.tV&u^%8 [o}N"a X>mӈ f{5\Sg_+y}ɶնjfv*^7~>&ۼ$acݾ;g e. [j1<\c%Ĭ;֪ͼs=w&/ O]a~f9E"yBdTY%BR- 0QHM9:Ko`endstream endobj 661 0 obj << /Type /Page /Contents 662 0 R /Resources 660 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 663 0 obj << /D [661 0 R /XYZ 72 702 null] >> endobj 660 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 666 0 obj << /Length 1874 /Filter /FlateDecode >> stream xڵXݏ6 _G8$[->>b_bԱoC> %H $I?mDpʏVTwe!JnsF'Lc v(Rkg:w~ܽ466F*b-MAx4:N6'POMCuE<~8hɣ >Sdh!qƿ7'9s+"an'-fFsi`@Ű?02b}]y#*fX߹/ꆇ/^:Ravj>w+>MXKi^Du6>K +56œfnY& <Ӄ"fjb颮R&*uH " PUWtocM6ҬI+nŗ$qendstream endobj 665 0 obj << /Type /Page /Contents 666 0 R /Resources 664 0 R /MediaBox [0 0 612 792] /Parent 647 0 R >> endobj 667 0 obj << /D [665 0 R /XYZ 72 702 null] >> endobj 130 0 obj << /D [665 0 R /XYZ 72 680.3998 null] >> endobj 664 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F34 321 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 670 0 obj << /Length 1683 /Filter /FlateDecode >> stream xXKs6Whr 5h_8ӤI&I[,R[t],tA0/tX˛TXra I*#S]QWVK&[}~0L/$f2J줜}}v|hC25 pT0IQRT>2wCW}Fs2[ZDA}&R9?}s>]mV~ nLXw4x^TsPMnlܨՁ~(S1 lljbS}ee}>VIMiAB:)]/cp\jNs-Y;ںVFJϼ֪]n]Cߏ X#-83y#N {e %UqIY A)rj!ۼ@z s׌wZ{YPn!b//ec\Vt{}g-qtBFdKTM挶|ow֚w}`~,H|5YJyu0CqsCߖI )`G]T;H=" YM1?Ng.jj2\,\\pJ/A\jI`"؊^x0|MB4]4얪ZNeɦWK/-0r9Kz d_e kz.jCƹ4 w$U3pGҺ^W;4Ar4}E 3]D=<{d]DWG8(ဢ2Gv/'pؑR+5cAxXO@.S$SVal(=멋Yv@]QECJfvR-..vA7Гg>ޙ^{6ֱT]>bc0{/Ysw(Q/w 7Gt@n [ ,0;\`YsE$k9 K7c*C*.߫UW>ЉF ֖-nz;g?#t ho&^*#@ ys&*3ڞ0 RsMQrm+.N" |Ko8YhHV"~lk.'O4:64n5`s2Їí(C&ñ1E XMBOZHENk+qU~ 6q[ eNL~D#!`bfz Y򖖦ZmvE_8+l(tkbqx;ʆz'(;|B1+mZF8Y-x!X 7mweiΗ}׼> endobj 671 0 obj << /D [669 0 R /XYZ 72 702 null] >> endobj 668 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 675 0 obj << /Length 1438 /Filter /FlateDecode >> stream xڵX[F~O hUj*j>`/km}eb׍3648F cτ+̤B޳}X?|w?-gw3#Ice-c7ow3 U2 r~^vjЎ(4&[-K{\ʍ|]9:fRͥ7sK%5&:ʢJJ[ ev ~&l/ BDad3ޠSzJN7x C#[)ϬmR%:q]gyGPkIT }TK1rH&ɤNҤ\Sd݀9eG)}Du+ lj0ںȚ,e]OgFyO#;ie?U"9Liε %h9gDv }+ܺfLs'0z^c ` $HN,$@|ffڍiZ6EW&n(ڈ8F ߗVL+FPa㉝@m_-+m-?x=yM ,ִA\ մ׎H].fm$ eN`"o<3oSUO,FƲƉ%a "P2MN*O < 9WzՆCOym]TYC+x =ڸbTH\}+Ʌ+.~> endobj 676 0 obj << /D [674 0 R /XYZ 72 702 null] >> endobj 673 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 679 0 obj << /Length 1168 /Filter /FlateDecode >> stream xڽWێ6}W@/rqIhӦ@4h$,BeqW!eݾ~pp8gD3y ʽf~[0B=Ah,R\#1L4a{NL ϫyI%V['zeM(ƠTHi bjpD2ƞO]2&<97 ~,e|e-̦ LnDY۰.>}]P$0Tz~P->.0wHPsL>0:MS/%J{2xw ;[^`1 2wuR˶Ozbφf2mmWikuӈfM``2I6guV㮯Ɲ6eh=@n-6Vn*̄`MyrS H;}[+LEp!)cI=V `@6Y78X(gE`YY^eUL,M g|p<ÆWNg$E9ҙI#s O0RE>Z='Up2E<|S 2+IpVymr :Dm6h-*Vc i?SaUVMr{WP<'6to}Y H@  %|i]:rRlcْiJ@gJ[=jVu/[sB/pVDŽCIRҧ  6GY\nVϾ:ous* LaSٞ> endobj 680 0 obj << /D [678 0 R /XYZ 72 702 null] >> endobj 134 0 obj << /D [678 0 R /XYZ 72 302.4766 null] >> endobj 677 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 683 0 obj << /Length 1767 /Filter /FlateDecode >> stream xڭXIs6W(gݩshi'iV$X$&]D9tto_9Grq9_f|_fxzP#F8H;;g O|\ b~ty3?1K$9Zй<7d%!'R_tz!.\T8l`5UzTWes*(*%g>OA3΂$0L&q20bώޠS>G5ea|' ']pe줠ڡ`E @ՕE~ҁ6Ύ 18S9XBFd oߊNZ5T^$qn6dboV}T@ BTR=H.$)<) cHCЧmv0\C0_C?b0$pwp8U}lCayfлC ?/[=PoObo,NԃuB/l_ud;YrQt感Xh4HlL&[Ue:b-ǫVh$|y9x;. :\Hjg^B{}Πh1o4 8CZg8V`δIjTQts,WD9ѨxlJ9JYڰ){*USEè% d2!B%q` Hnqǵ޵!ʼn.{EsFmݐjZNl/ 2?%:/i!}ch ~%>V4רzji/MI_T<@v`P Cso?LslM(F2taQmUFW@$16o2ns{G ]BP"T>@oo{ϥmh]C` Ao&z6-\ r > endobj 684 0 obj << /D [682 0 R /XYZ 72 702 null] >> endobj 681 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F42 469 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 687 0 obj << /Length 1502 /Filter /FlateDecode >> stream xڝXko6_C !CRԃKbu@X Xv9Rk-wH!@DKG^{E`#ANa uA03Vg(;7.q%Iǜ7kŢ7u˄٠q)KXr/xʱ$6U3Dz)Ve$lpw$,f?m=gi Ni],.vR9A+b.NqtvVlNSuB'(a4c`'#YOդJG  H s,:Z9 줎s#V6Sl[=9c$Ed1ڌXجWc[$24 |h L`XQ1(NivվS}PѡTݽ,yX9F;b"ruL]z8A-JŴk}ەϗ奯eJX2A20s\w ~晆|Ya r| Nz//2Ιv(g<ܫU8(wJ! >s>2>#|4bfm~o .k| !ټs Xߴs,s s[z̩vV 2J- _ Cݘ2@8O?jl2vR9Ac։ȰY?L-Sd^)G9Q\v3Tx(>Sf.ee]_[|ćJ'B)h҄O I](P}Y^oŮ+UM]OPblƕ\`31Z T_$9|fўGauwT׺эm/}#??zǗxy^C|h}M)yf#0&/;dW 'kqDa<& i<]Νt M0}g,LoPvm7Tglhޯuw.'վoaTMNlu ̮6e) 3Z7lZλl;D0Mu-w@ #VC8:($B!:Ag̜i0׭s* `}[p# L{)AƁY9_S0ɽ1tOa7G)>-Nendstream endobj 686 0 obj << /Type /Page /Contents 687 0 R /Resources 685 0 R /MediaBox [0 0 612 792] /Parent 672 0 R >> endobj 688 0 obj << /D [686 0 R /XYZ 72 702 null] >> endobj 685 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F55 489 0 R /F42 469 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 691 0 obj << /Length 1123 /Filter /FlateDecode >> stream xڵVKFW+y22GJm](ظ0Nr[<cTT0;o ?xxq%'a x.2ge Z/7Nzlh9)rWd{~_7~_߼I\޻R80I!WɓN#û &Q"풮J$̌0np V'R$]ީX/;?,#V{/~1 R!xfv 8YkL8aVi4vmT&v:SitU A°LIֺH/۟Ppi}de,G]?F A1(CP+ $yǺ}EC xHȀ3lH5VE Et)*RyŀgJginэ7;duĊ<י.oXc:ަǵsiI+cciyP ^JƟ2Ruݔ a btGoX+&d[pK_}CTčW+HK:ƭp" mS{nkG)H ^0NWUBBQ<&/ƹp(@(Iysvc?+@ff:,nvzj'Hg>yLxi47,R = Sfuyu.9;sw6ʿ#8y/XX`\> endobj 692 0 obj << /D [690 0 R /XYZ 72 702 null] >> endobj 138 0 obj << /D [690 0 R /XYZ 72 680.3998 null] >> endobj 142 0 obj << /D [690 0 R /XYZ 72 307.5936 null] >> endobj 689 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 695 0 obj << /Length 1429 /Filter /FlateDecode >> stream xڥWK6W7"EZ@4ESƷ$] +$);ekkq8/g '?$IM׍; V)1Z䠯&>TxI?67/EςL8;b9vݫ3JU:GͤY- Lܔ c?IS/L Czm5 Sc[ݝD $E͛wS[6eI<"efatXԛכ?G=AkT'aEp3iq+dtO+{"#I"k(%ɖ[77[/{2ǖL0/ fK-IeQowu{WqVn!]E0E.}ZU,W ?HxW]57~Ʉxw{4(TCV$[[u̒OmQw=({k5PePVD- [b$wK(\`L.m#J*`#2 yHyb_$͹d6PJA _Z7wUSv6p+'o(`6(z+4U3 ڷޙV?A;A.u꠭XN8&nu;xx+'l./\|xO.WB^ǶMq#hBիpVd&Iڬ$D[\`Q5$z,$XUTH¥ TE52Fh[ bMybZXQ@<,B *Ci9IB. S*qw[oBCY64sǿ(0$&~  mڸEzBs@>sP;Aj ,Q HjnR`{B6u70> gQPK>Z Kжw1^Fe;羂#4\ 1.#t^:Xpju ˱';!?^#7mSٮoS뻕PRչ9b1~x҃"8~*..eLd: XO[hq,} 渼OĕW/͞yFr`Zꋇo|*?"[N_YET~fJB\y[74\{T}Xwq' a'Q[^5a `= CoX c?endstream endobj 694 0 obj << /Type /Page /Contents 695 0 R /Resources 693 0 R /MediaBox [0 0 612 792] /Parent 697 0 R >> endobj 696 0 obj << /D [694 0 R /XYZ 72 702 null] >> endobj 146 0 obj << /D [694 0 R /XYZ 72 536.3098 null] >> endobj 150 0 obj << /D [694 0 R /XYZ 72 138.6986 null] >> endobj 693 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 700 0 obj << /Length 1478 /Filter /FlateDecode >> stream xڝXKs6W"HLi:NmtKrEHbC.Eq;@Q2ϘbX|ŸpY aVBGa*s^ R tAߏ|>0߬w"qDP ga-cU~t_{Wb9eK29?F5yTTӹɾezlOOU8 <;5mxq/n[{~KC ~&:d\|:%~r&a\9Ls;rx6̝Jfq 8~IGp=Nx@P>HNDI)#`$Jܢol5궽E"_ĠFEkh&!m`vQQ&Kքvxtpݖ[F_;}G2Y0NQiX T rjdL>Ϗ2U](# z&(ww>I(d6%̪ {?g,J#2pC}=ЬY7`G5ӊkS Fx4}%n#3ѻcvpp5zdxk`8@tTs*%5(8!-8IJ TD҉n qNk7O\&ouov3YUaTD,=OfM<ԑ@E"<ץ 7ZZOTeQ~u`#uB34`lsIy.9a\6a0M]Rxtع'6z6PC7/Kȗ/9al|2Z?m6hfM_Qn"G4bgl/"&4c&L g:(C0M Q7:SuDiۊmxJ~Mmx |jxV Į/uBq 1&cNFҘacwmx`LK&A]TTWsIV6aeKm"-Wf.O8hQ1~pGӪ@ԓ1kVJj??՗/ѪJVav;1S}^ɿWnsC5 ՛g&%~RJ7PEA_蔄 (rR JX~XŞIA'vLO UX^63Փ $3<\N/rdLGx jsi{ BͿGYʏPt|1Ki qc}q1nOp`AK?|X2Gv̰Pd'qdI^^6'1NjO+_endstream endobj 699 0 obj << /Type /Page /Contents 700 0 R /Resources 698 0 R /MediaBox [0 0 612 792] /Parent 697 0 R >> endobj 701 0 obj << /D [699 0 R /XYZ 72 702 null] >> endobj 154 0 obj << /D [699 0 R /XYZ 72 378.4857 null] >> endobj 158 0 obj << /D [699 0 R /XYZ 72 191.3948 null] >> endobj 698 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 704 0 obj << /Length 717 /Filter /FlateDecode >> stream x}TKo0 WhH(Êu@8Nbĉ;?(Kv(|0E~$?)"QRͷz Aɵa "zCX9,lhqY> endobj 705 0 obj << /D [703 0 R /XYZ 72 702 null] >> endobj 702 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 708 0 obj << /Length 1184 /Filter /FlateDecode >> stream xڍVK6WPqc&mSmߒ֖\Y zث 9o^$E'"+#e9xtW"ptwͣ4h^ݾ729mmޢIc8Lu9~˛?>&_@TE1kME93ĸt(z= krN< ©H0礉*ڎZ#3U\Q_2mKTgqaT:&D&teZJ12*Xx`!}ER3[9Z@~t4ajޟM_M"% w^)UZԒ\sT*;X#,"S"@$۷RW;KMtKVݴC0X7ƛFZ-O,IzH]? ;m 3IO)vҧb0@t XCGdWqє D$*fT#ҙro2:4J/4hS/{ HQ BV xEOxcܹ,:6է_o~[: ߱]|'UYZ…]eRɮSo\b#endstream endobj 707 0 obj << /Type /Page /Contents 708 0 R /Resources 706 0 R /MediaBox [0 0 612 792] /Parent 697 0 R >> endobj 709 0 obj << /D [707 0 R /XYZ 72 702 null] >> endobj 162 0 obj << /D [707 0 R /XYZ 72 680.3998 null] >> endobj 166 0 obj << /D [707 0 R /XYZ 72 321.8943 null] >> endobj 706 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 712 0 obj << /Length 1101 /Filter /FlateDecode >> stream xڵWߏ6~_Aԅ1Vw=u+]UU奺6@ʏݞ Bij|qC:1sbœaEH~XQBY jDѯ'*zuH#@EXu}}Y $.xJ:cKstOMqDWnWnڼ*}}ptX}B\"AbLIV\~R>~a'=&TR:BscAKȭ+Z#SD]]ԟb9 s(B.z>p an|lr iELhړ[y~%GM| '#@ 83v %,$;UЃz^voFu:OZjܵ;hsǤ6-B@ uS ,=$3fۼ>f)f:/[3g4 tI L+mC-1U2.e,zÆ~8y֒VuZLEm|(,z,pFOՂnsc7M?LƖDX$~D{LGK:ݬNd%jJP#F%60QxG+\Q/_$5u5pV'PW/rəmIs r,Ub}V Uma HNQ}Y|/*] 4MgH=|&&5 F`4z>VbbQ gɔgByi(>$˵mezΝyz"V W!:(]۶w4cR:/Pnh3pWzޙiS`["nVt;BZcaT|@Q,dWgZŧ%Wm}:`ڄ+&7+j'Aij0U 5/`^z2} R'+=LO^Pbx?B\(by~ Q;QGXxIcPK~!!endstream endobj 711 0 obj << /Type /Page /Contents 712 0 R /Resources 710 0 R /MediaBox [0 0 612 792] /Parent 697 0 R >> endobj 713 0 obj << /D [711 0 R /XYZ 72 702 null] >> endobj 170 0 obj << /D [711 0 R /XYZ 72 574.1325 null] >> endobj 174 0 obj << /D [711 0 R /XYZ 72 176.5002 null] >> endobj 710 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 716 0 obj << /Length 522 /Filter /FlateDecode >> stream xڝTMo0 Wc""aau=Ns͵dIb["#"b~)a(;=ǀ8&k Zq],T J0(ٹ*ln]r\1 gd(5 VJzs=q|ZkfU-&i}Ŝ0;A#* Xqf.ul\N= Sk$%` Xݻ #"/g-dGLXp`6 2ֱ6m퉟V6+riz/̈As\.]Q6};/g8:ӳ>{Ϊ^vTɳ(ǭ7a &w1?'d@ZL^Op,( ӗ}PL-BYgP'/k01Cvgt_zxftL) ~NːM O;+c0.taNendstream endobj 715 0 obj << /Type /Page /Contents 716 0 R /Resources 714 0 R /MediaBox [0 0 612 792] /Parent 697 0 R >> endobj 717 0 obj << /D [715 0 R /XYZ 72 702 null] >> endobj 714 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 720 0 obj << /Length 1948 /Filter /FlateDecode >> stream xڥYݿEf`*5j/I_k;çtW@ß 8tۍ^ۍ]A$m>~$Y9R%w_cOvhBe T+gLz7SqwďD,160(b up^eDyWfȦVic 76Sif B|=llrUIU9lN3E[8 *%.RU+GZ&aF&ċ+^|jdE x @FFRqu (l،uaryu=/+b(;|'!d_8qZ!a $(~N_p#EM /O^Xp?\D"iguTMQjbSvx⾙<Dmɷl*v<τGBo"C>ik1./sN` +҃ZGW߶%6goQ\ +m߂!jyxOÃ!atoK[ 4e?7ϧR<VyNŊ*&lO슨.9$&'C"]Mu8^;(|#:y=PW΃Ṯ /*Dl6WS20D,n'fʮa5sL`k @L%[xSS4{(ХgwôSi*!P$k[urS5*Kܭ(x▌P k9?e#YC4"xQǦVS[B!`6BB?p᠛t|qW fC7R*R אP0O*G̪xb$C.I%Jx#,( j q dX-q )ጉ-WXu9ܡL)2e2})O0* 3Owx1/o4L9 n8(Jn`Pf?9m~s(20~ӀK?016B'tǴQɄaz*+>1$I3Iʤ Lh4.;*_ d9 CHF憖%ի AQL}3jiWAO_3)и⑼>;:ӞLo]tdh N3>7V20ZL3~@XG&;{oM\ÓA1Ci;$o]8#a>?mf5nDri}͆ rFWG#JAg<2 [)ʚ~๪fhԽ'Wmf0P*fff3Ԡ\>0uPGwGuu?6g'g*t hlB=YR<O#Z> endobj 721 0 obj << /D [719 0 R /XYZ 72 702 null] >> endobj 178 0 obj << /D [719 0 R /XYZ 72 680.3998 null] >> endobj 718 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 725 0 obj << /Length 1719 /Filter /FlateDecode >> stream xڥXK6WhH=vEѠ)6{KrZXYr%9H{g^- Lg3 G"ELx݌yO0I26k~"hg[eWg~=lxX[|}x!}PX& Ъc? ktS{J2G" V/K>?t:.Abm,iĬaPͤr_2ANk+`U <0_$qf2C>4chAdxHѝOx\ w&,{K4zΊ'xB<05NNdy^@0`G}DD9z6`)";*iA^7hT#CׇS\\o&o)Ka`~$ou'%"2S}oXժnu0A9,h YtS҆зR@nh}$2ƺy|Ej2I|x1!NwDUG6u. AqP,k|Cuޯ=%:U^Ru_Z|RiFnB'Nw\/GS`,ʖږ}jSkA~_Mb9u[r+> 1S ܆Qp>~=9]RoLZEA U)w#ήJ-Afz/=աJ( 6YnD4NhVtmXUPkk*rϟnG=A= l<ī O[Z9 = # W$1I5ٱn!ܟbVwCg\b]e%Z0s!D0 G3d;sbЮBSrH˶K1qae0gMm;Yna"rİͥMQ72"KdRa*ijWl Eo-n<}'" p`WtIaǥ3\kKJcon0nmfL_pЖFc#nv0$ !elƉ3 eTwJf#nȏp4mI_qL.tO>{fg/$aً^_h͠O7[m?&~o5ߦRr?LBO{T[lHE#ƣ)v => endobj 726 0 obj << /D [724 0 R /XYZ 72 702 null] >> endobj 182 0 obj << /D [724 0 R /XYZ 72 655.0513 null] >> endobj 723 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F51 451 0 R /F31 314 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 729 0 obj << /Length 1551 /Filter /FlateDecode >> stream xڝn6_b-Ѥr6SzoIĭ, ;ÇZ Ё#p^CcN; YQ v~[1NHh GbBB<`%4ެ?ad4cfhM|)miOEկIL,Rǖtg^$xGѮ[=to RPiJs5ԗN{uJ(KR?Y9*SSVL|BX24 )OE3a)8HDw}"?r5xVITZFyilx;Au+X@0LKֿWWa[ba˗-[5z<7<~ onm‡[pQ}ފa;m܆/Y'fi8]۪WB/s(vU]ZN&vQ'-n'-?%q1vsBSkB,${3@p"A ݞsl1b a# f)A9+t@{X7\;Tv*< 0wXH0pbH${%UWy r@MDtsY"_fiSѕJawp`}I©dm 3AňDPߠ;])X)ILރh M n Իc?k؊2J@"-Y]6Z"ĻdrQouYRcˆYź"1(F%ŒMщaQŌRw^'kKPd{5$ʖL ]gһ}?%߿WùTXL/wKːDev#"OfgyxGӘ yV|<{cC? {n I1/U-,N4=6?@yh$Qkگ%K(!> y\nendstream endobj 728 0 obj << /Type /Page /Contents 729 0 R /Resources 727 0 R /MediaBox [0 0 612 792] /Parent 722 0 R >> endobj 730 0 obj << /D [728 0 R /XYZ 72 702 null] >> endobj 186 0 obj << /D [728 0 R /XYZ 72 449.0678 null] >> endobj 727 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 733 0 obj << /Length 1341 /Filter /FlateDecode >> stream xڝWn6S9I@DEIMC@m=IJ J[Iׇ{g8$-e'-gG?CR Ae;lxp+?o@1UNo/5LD槭WE5;c{dJq2Ҫ}p"<1 u$O²U#b<7x*ͧ/<"˃;Ly6J|lXs4U޿to!2, .R0]\Dq*Ӱ5zkWPWERUH#P3+yC^@, ›$숸'$T8AJy $pH>yҁ9z%"7=lиR< ٬Ć7Cxg/#4H+,]8 jy8^%V%"OMbV V!|Bkj8*]%ͺC'6Fu%X6H?T _<2%JK$RƦݙ?(4]PDY쬥% (L` 87 GOG1ee)]ݓX5ϜXg'ZQz=gaVD {}YnugY" v9W1LF 1i#F }hbŲ,X)n %ƒ}-@tu7 p W&ީF'J~HEM Dsό_h}v/֢ iZٷbw_}^(WXJB?1Ix3etC~]!!{^HțՃ~"vJ{*jx(9 z ͹kږX7drc8Wgk粻q5s}^ e|rnGݣirajޤz|uCp"j"6Äf9DKHLKxؼ%pr ͥMS9/r9ԇK]gm0z)׫oZ=-wϹ5/v/?a( QڜGQ*>x^c0o:*xIgͰO{Z<`h*{eN_,\t3 PYz># l,ʹ~"[B:Z_Q+^endstream endobj 732 0 obj << /Type /Page /Contents 733 0 R /Resources 731 0 R /MediaBox [0 0 612 792] /Parent 722 0 R >> endobj 734 0 obj << /D [732 0 R /XYZ 72 702 null] >> endobj 190 0 obj << /D [732 0 R /XYZ 72 470.134 null] >> endobj 731 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 737 0 obj << /Length 837 /Filter /FlateDecode >> stream x}UMo0 W7XT}:l;l C׃k1l]GJrP'QyǩS&bx ;#<,Vy51 Y_p+J9?nkcΨeǛ% 6-ymn.:eTeBLD|@DisLeŧ^Ao4b˜.HV+Jf]u=BL LǔSńwt{*6gX0*lf]L6/h};w`V I~"JeDKb1kDr2aՀW#_;Bf&EEOtq:o*T 9Z.ǺFͪrLVBed|ߔïDd`IIΛS]t OU"·W޶}z)цCCFl{=؏!̥z:ra8N=BpI 1SåP9,z4 r@ƕ&=p@fc5CBn0p=tp;P~:BLp1ɑU>լ9>P隽]9")A NLڒ gM4wϿ 53,qm|0R8zz!l>ϽyNuv6^nXON&q ֌Kt=AJ q;Jmn=^Ū|4'j[m 4'_bi)9˟כ1-1Ȭ51c}\`3- Tp\&T %N޾4ƚ4@yagXiSjQ .FQ:endstream endobj 736 0 obj << /Type /Page /Contents 737 0 R /Resources 735 0 R /MediaBox [0 0 612 792] /Parent 722 0 R >> endobj 738 0 obj << /D [736 0 R /XYZ 72 702 null] >> endobj 194 0 obj << /D [736 0 R /XYZ 72 658.6379 null] >> endobj 735 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 741 0 obj << /Length 1562 /Filter /FlateDecode >> stream xڍXY6~УV I@JQߒTk) X%eu},t$8yx1%[~-xh} 3ڲ4;i{صf)krI|JMݩUߢ<ۮ1ѯHT]jzrEKƢiؼ['Uk["氿|A-V)*Nw5['=s`fc$Ǿ!lŁ=I_C=P9R S?fv:ET1e\>qwIXʲ[d9<'4=}-_j eY*z<<'.t`kPl(2J:f[jc5Dء {IQey N L?}5C*7Z4JEbVvy2'pu#,̙J$,+sLZ]Jus/ƺpl$l L: F\?]VZ{JH]Ur}9 Nd gRqCLןm]?l]i:xN.]z_6=~ݮMH"FBS%٫($(Υ*mb,;Xl+,NDXT汿*wۥKe n2T$D5UIl92"-n ᨷ.vi4Z (G q g/?-RDhaNC zsyv")&mGI 1sH,)!>i*.xIVCq 9;̴f>"sqYtq= qk~N-Ä27`5f܇Ŗ>[.5h&}:4dԼ48 45j;Cs:;W}VI&"`_"R)8|+hJ~V.NCɻբ5 d0^7aZ15VLYe$4Yo `Θ΁,e N~,;3Eoެ-5d%t߶PARaGx:゚Me<Ԓ#H+Aa+tڲ/\\X曫AHUnX|(V?+|ThV"&L Wr¤ 9 9Գ¥ҩ[_MV[3E/-x-K1eQPOendstream endobj 740 0 obj << /Type /Page /Contents 741 0 R /Resources 739 0 R /MediaBox [0 0 612 792] /Parent 722 0 R >> endobj 742 0 obj << /D [740 0 R /XYZ 72 702 null] >> endobj 198 0 obj << /D [740 0 R /XYZ 72 680.3998 null] >> endobj 202 0 obj << /D [740 0 R /XYZ 72 220.159 null] >> endobj 739 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F33 327 0 R /F51 451 0 R /F31 314 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 745 0 obj << /Length 1589 /Filter /FlateDecode >> stream xڕXK6 W(Mc."LrHt)ƞFwddT(Բls2tQȾ!H :Q=JL~CliMַt4 ]#DߔhcЫz[LY^SaD^e֭,z#r/4[w&(MpklďɟG= HMNI1.KKb z^c_ݺٽK{CA]ޟ n"xg^U>4 5 Umn R`b ͔S-ݴ=kE:?珺>,xٵe3@}/Ͱ T/E[y_0u 0:Y@|Ҿ:.QrNsbCvY~8)Rcadm'Գ/KЯTVRE$/{Qvvl%sTSUNkҿc@oO@l.`cliB@t?eli9EҦȷ>5s/5`Xpvo|ÏX7= 3c19ڇbBxhPZF"°T|jf*`VCp¨RpsDYIayj8`HQl]$0i4gW4pRX}J?v^5>;y.z'9AAoPu` !VH<'pߝvaI"dɇlʌܧ[<+i1dp<^R]+w4Ƨ:V@!pz#}=Ur׮k=,UaSܗ_#Q]d،2ں݉ytYS&w2)0c;7M]Hi GܰQ_AҒR:d_$JedU[C}xLtfhdD!LAH .1'n?7槆+oF܄ONmD1fw|1/VoE-(@dl0nVU}6R5/ VEx@L'kXhTP[ڳendstream endobj 744 0 obj << /Type /Page /Contents 745 0 R /Resources 743 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 746 0 obj << /D [744 0 R /XYZ 72 702 null] >> endobj 206 0 obj << /D [744 0 R /XYZ 72 156.6272 null] >> endobj 743 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 750 0 obj << /Length 1000 /Filter /FlateDecode >> stream xڥK6j2|G ȡnI% ,Wl?}Mie cI9f<$QRGzG570r*;@E(I -VJe[SdŧKaP$T*Z֊ů_F Qp)J H`}^&(. $mdŏC!@!6 ^|ByaX  E-Zfє(cK 5@inH@)FRTx&Z-Y|ҶGqnm*w1P)&jʾ֛ݱ4[W姲Ϡcgf{nBvPac gȠ5Jrjͩjtkt7 dnjCt&@=N!a}՛wl}~+` 5^TJ=$IF1 y$CI/ I+U m^3t*M^dfz ^6 5j2.PuVTGGTCE `Lz j'5iVggjmغ0)ʔպY&Xk0ʭyhCZ?.Vi?g}%MeW%M:,էSտNrj`mq1IlfRꉤv[l5h]u}&Y#شWj4aD3Sz6_oy[U ͫs:b̳]X' #<=m9kji<2S-A7ːcSjU'AΎY6sA6TODˮFgȕC`xaӱyxpdn@ҹa~OY{S)]-~Z 8o~K66S'X|i?3ɘERV|Q8?endstream endobj 749 0 obj << /Type /Page /Contents 750 0 R /Resources 748 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 751 0 obj << /D [749 0 R /XYZ 72 702 null] >> endobj 748 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 754 0 obj << /Length 2121 /Filter /FlateDecode >> stream xڝY[~R"f3@l d6 P $3({/%Kn1|BD HH&4:7I #$XX@AnSe"z?nHxDX'DOI<~7?,R1SLÜ(=RZE!t{/t4 Kc8dJYuG#Hjߒi\K]T+7L()7lc6YÞhDX2A1c6N)R"WXu&ۺ.Oz5zs*)WHтFE @3"t vmWfGֲ TV .0ֹ!cPh ꚺe銳23pӎ!ƥG{MDriKY/nXUvE6U?iJX1%TSk y@zΰ_P,}CK-2LaDHI2ifP1TQB5cbUy>|SidITyiXixB%e @`M^쮪UߠΫ:DbUϞ%.MPg8V/@Ac“La#^>Mm 2WS:+FZp4oK5{Z_>E]z!@N񓄁Lm s!s;]+RKtY_]}.+Dm/>V[UT0=610kܨP,󣝥ɏL;zqs\iu>PE籆çCj6ÌǙjĹ Vޚ9Bu]ɺU]V.X5DmOvRFe(j`}iq۾s})Y?j\k<5y[46E]XfAAKVqkڨ]WHW`$ UϹ"͟/maO返Eäg %e\M 1R@b}w6dUgv+&rmA˲KXǍefqZY<UG^xJ~1?4&ŵyOprlIu/M\o9l[U}o o 5JVuy]G 1^گtW5_[߆6_.EMbn0fAJQz/)*h >ݻV%DV~?_s[ -V 2;}:kqR<U[Nv&7uƎ@ Jk_GR̔ 6R<ʎ]՘[Av1Oo~*9 ePT Uհk {q!C3K{y"?~aZkɉl'pIis({{yO7yj=s}@PrsUxE9EGD,19jΆ$X_rsFb͙Z*u _\ E1:y@̥#Ɍt]͝ /R$XK5"S*E譱D4zLN E80O Ρ)^HmRSEߓa밺^6E Em&)X:ī Sm79ec4P>XP5p֏ߺM_Yr=$D)K͹ B &xn8uMB7nD(WP` >4lyTň1#tc$qxS%{wSwQ,?=`GhnGOm;2)Զݳ„ ìB'EXaA7,2z&nsҜAi(K1<> jY"sfn!#ٔϥUDFKT.T-nFendstream endobj 753 0 obj << /Type /Page /Contents 754 0 R /Resources 752 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 755 0 obj << /D [753 0 R /XYZ 72 702 null] >> endobj 210 0 obj << /D [753 0 R /XYZ 72 655.8483 null] >> endobj 214 0 obj << /D [753 0 R /XYZ 72 224.4993 null] >> endobj 752 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F31 314 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 758 0 obj << /Length 1197 /Filter /FlateDecode >> stream xڭWo6_IĐEZ-a>(b G*QF,%\zy(pO1UJW"5LʀLDA&M&NMs{hJ%iϭZu (`]"M i;6_V?soֽ_q$0LxJtT՟bKŊc' LKc SMy4 E014ڍn+/ւPDH+G\_;~Cߦ=4e¸IWuYU__۹4c^<*(c\,ses+`\KVu(%Ii&D~}mgB/Ng\)$eU>E_6 ]=t.qW4K@ w-ni Te}D!8yO0[ȃI1!d`_&!p#͏AiUE3<81/$X9?#mҗӹsef[6 Bg5OGg5RJX'mrڒKʻl+*n=ƫpYVPBԉG0loYRT%{gǭuv,%+次IԙU}a+Q䷐'0}:j'T]GrԈ7t !$& #u$}a㙢/46G[ 'I/~SuHJ`;aHtӚl+z0|NNkmydsӆtBƍib{Ϧ`G$_Ϧ 3¦3;Yݡ_6Y႔Cx6YTb7e>wB+.aesW6evrܕq}w(ߥbf4,~)`'}Tkk!.CRۚt`S*"s wGai-Al6Y'a?q,II!:= %>ibpnendstream endobj 757 0 obj << /Type /Page /Contents 758 0 R /Resources 756 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 759 0 obj << /D [757 0 R /XYZ 72 702 null] >> endobj 760 0 obj << /D [757 0 R /XYZ 72 660.0708 null] >> endobj 761 0 obj << /D [757 0 R /XYZ 72 460.6266 null] >> endobj 762 0 obj << /D [757 0 R /XYZ 72 284.3036 null] >> endobj 756 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 765 0 obj << /Length 1183 /Filter /FlateDecode >> stream x}VMo6W(BJ>=h lC=A$z)9Ҷ̛7e$OFE"a%=X~]I#"\`pA?~)D~qizx:"D%3gKqm1SNeJUAL_4eTyUFBx6RYR^ښaqdec˓A@ǵoQu2Q"%"|Q >D^a!*hX ~7XXzI/8HJYQWRA9vϼjNϟ]ԍ9,L8[K4%ZU)xç_7hg?8%3-Qjn_Hg3|ΓB@i~{bY.] ٻV0B.U|raM⑱ Iɺ`:Ң>0Is( uz`q' m>t-sG\ v:-c3UHmٰ|L)bnc&H-,r$x[Hy]`HE'ُGJ|Lfzv'@%טqɼCtgu4neRJVGoMz']2KΘݔcc{@H4SY َ*=I a5=:󶛗$W3ͦ{8RKER*o j+E6S@ T ^϶NIX 1޷jh㎡S`lYGC"f. {WCws4 ‡ mOk_ɞB+j8 9pHti -ۑob_8D{]˄PyDn-(ܛԄ=AJH ?_hKHrC}dt`O<\nUAZn=~0t~p9t ؊=wt~0{q}+0=þ/ [Si}M2Խ-UFA3C:fj|sbt229abjO׵a-eu@{ h,p/nyendstream endobj 764 0 obj << /Type /Page /Contents 765 0 R /Resources 763 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 766 0 obj << /D [764 0 R /XYZ 72 702 null] >> endobj 763 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 769 0 obj << /Length 1347 /Filter /FlateDecode >> stream xuWݏF_[tl{YUԦEMyH@l|&l3; 2eN$DdLOJD9.02yE7g?żv.Q1Yd{>כ?6/s&PΌ@!݌$7L>* D)Μ:{iLTd$Ε %e2m5B$ a!.bx|z~ѭg ƍWcOf.wIFf6-O;ʦ0s2 fC䆻 ywZgZ"_txFLgp=v-]RũgcG}Ӓ$<ŋۆmSJHC[EXDW BKRB S]DCTHyMi! E]7(s]gJEU۞^C`4F6v/rĴ![R2-ڏۢ} \g,[5nW\iX^H f!@tá$ h\jР@bַ/2&z Cw3ACAj@ҤV=`UItaOlEhsq_2ug:bLzIb/xOmLW&ƁfwK}2ɔC oヌ W_?H1v-Mׅ?1rh`3öt1g;41QSK߬nt q[W]}FwQc6=Gu=Q0qtO,J:z8m}cd| o:M?q(#^p 2Rog(fyW *ib{PX(MI BxD&Vwϓ…NQ} W,ln*dXA^LT݂5E[rW8l)͡cx8'bRK+hP6NǙrnAyB7c^|Ԁd/?ɻsUg63~2JC6vtwC9&~^#J t5+mFV/6MѴ>^1bpϞatWn _KyRqvHǸL|*0p<.)oZ@,3]<{(%&Yi_>fnK.G[þ=sӺBa+~iɠ}@/V 8+ko*lRެ~l2q+:넉4qPjiUa6sq6vX].B_#CjgXe3=nI2I!?M%endstream endobj 768 0 obj << /Type /Page /Contents 769 0 R /Resources 767 0 R /MediaBox [0 0 612 792] /Parent 747 0 R >> endobj 770 0 obj << /D [768 0 R /XYZ 72 702 null] >> endobj 218 0 obj << /D [768 0 R /XYZ 72 680.3998 null] >> endobj 222 0 obj << /D [768 0 R /XYZ 72 321.8943 null] >> endobj 767 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F32 324 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 773 0 obj << /Length 811 /Filter /FlateDecode >> stream xڵVo0~_)g;PA %^&%IW!;8M`Ewg#6 y^}`! #.b\x F +/n?/«1A ›/7IP?tJ9:+cD!aL]ۜ@ô 7sÈ+{`DUDrOއUt\K t`'$DH cXu>K`$F)کÈSӢeM)Va^l[V..ܶ.//7r6鑓Gu`JU&nZfUqqhUՂ~M/^̶g7Z J-m\v]{Q7EYv-6}o]U[XSm;ʈk.ڕ(e]UgiLf~~:H3(7da1̏u@nã_QteIߦe6NC/.Ue~5gOʏA\RAw6b ĀTvW&.3E`Fq̂4m GȨd|oͮنQAX)d v뉹WFgVm;&B\o r@ⴔ 13uAG21.Dw юʤݑ6\g}~_ ~lug8!9S-X)1n0-SXKa/V}M@wJ`W5;I.EtYDЃwINCi Xdd:endstream endobj 772 0 obj << /Type /Page /Contents 773 0 R /Resources 771 0 R /MediaBox [0 0 612 792] /Parent 775 0 R >> endobj 774 0 obj << /D [772 0 R /XYZ 72 702 null] >> endobj 226 0 obj << /D [772 0 R /XYZ 72 197.0402 null] >> endobj 771 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 778 0 obj << /Length 1553 /Filter /FlateDecode >> stream xڭXKoFW"\vćI9-́W[tjw^KQ2mEkg*\/\fjj/p~Z,c?Hck~ %$,HG7a &\lًH7/7GTH DkXhek'8(JW:MϣzwXEʳ5huK, OLGx |eYqKmhHan I`j<9ˤz&MQWWu=SM~g[%#?"]YsϺ9rb*3m"Ng~e^|C'O19ܿ`Qk8k}E\GQufw5l^p ƿordE\*`_ID%ip5pDFNq6,lW8EZ;v`ֿiB4I&΢) nb+r v; 6 2'EHB5VI3f\\H|]L^g#(}/`,֫ŀ!U<* }#y7C;'vr.% Ҥ /O8XPx1*M@o[dAP7\r? oT(b4dU۶ɋMԷXV[i}LSmEl 2] ^AtOFʤL4-ExbB &Z<;_bK{]Ka]G\w"?MJ7L@n'Qq(єk@{.ʼ+ұqzo-kP5h,t)Zi֐eN撗Wƍ> 顚<ȶ5ʥ3-sӄơ.,,tƝ q;KM[(7>KDZD x* ;R)0p7P]xɞɼ8tڤL;d0 Pڪ`t/[kB|%͖H>&aܣPa冣{(U{t*Q:Qʢ G⾬_ e>ur~gͽ%S`ۗruye5{plyNM },H=`s'};؉@&&|)Oe=~f >| K/\].A, a'er8q@t> endobj 779 0 obj << /D [777 0 R /XYZ 72 702 null] >> endobj 230 0 obj << /D [777 0 R /XYZ 72 289.5152 null] >> endobj 776 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 782 0 obj << /Length 1235 /Filter /FlateDecode >> stream xڝVYo8~Ib(JlR[[DڕV]`C+JXx|pGy"ʽt=Vގۡ T 7ID|4e(Ih¼8<_MoqEqeNMD&wIzjO i@x,U7q}]߶95܆e`û%a&$NHȸчnX!BA|gyxI"(L4OIC֩7'<3 i?8:&, HܮBD/R4KXh9[}lqVea2@tqqSN2*vv<'WWWo2hĿ<"4]$`'cH`"LY>f~ߕI~ޘo+~=O opZd7clc-@6]j+\MU׈^H{Kmm2ee`[ы889 vK9Z&8iV`Zik J?{'P#f͚nW0C^^VDA{+ݟw82A1NoZ&"10}z@ j^@ RY +ܵ 䕡qip MZ>)wpf!n0b!|Xye87eΞ$6d0qZٳ][[)՚a4ۥ1ѻ3V9؄(~=R@ gIC@ NVVUWAٮI?BEv<B lU*Hv".ܴ.Jw^_ZLW8oWl+a!Cχ"BL7ù2b _QWTerʛ ;vx4ʩtu$/{ճ2;P[礪sXhlLiSfbjMHo/oBwMj^pF`wڎs8NȢr7n*R]C_]Z=Q85ZEmj{ᐟ4G!bgWC%~3mQ>4MW9YV[X@*HX2,Ulei]+k'ǭm禒:gqri?\W{zt[٩aDa$3ecF^{Ҵ H1endstream endobj 781 0 obj << /Type /Page /Contents 782 0 R /Resources 780 0 R /MediaBox [0 0 612 792] /Parent 775 0 R >> endobj 783 0 obj << /D [781 0 R /XYZ 72 702 null] >> endobj 234 0 obj << /D [781 0 R /XYZ 72 452.4495 null] >> endobj 780 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 786 0 obj << /Length 1298 /Filter /FlateDecode >> stream xڥWnF}WykW^j@k(ESFc%y)Jb".b,%Jf⦅!s/g̊ßb\fă%:~H'4"h[ PLbFo g)OE0[.1_?^QJNt qM4Jӹȓ\[LTndXTm@\}ă9vęI$C3&i(:M!N|yܜXRDE R5OQHf-}j^-]vUӣo)%_],^9APT"v` 'dflY7:n~f]jȯ~}C_XH JNVݟK~t1iq1F~wǝeb!vL% "0_gu:k[V"UKEP/hA}K,82IXXZW4i >0y 'ƲD N]:ZUg4:"VaԾkQ)0Pb׫2QP?s8K;m&c֏'IKȥbv5?' [|LC#L<1,ͼnDDa.6wО7Y1sBXVYSA@7l@ +: t:n6iD8ʏXVPNm%5NeNϦ$a/`,`_wWW^pUWs1(Dz@t 93fO4U6=#A|`햺qb uDž@%EZ~>z I5%_.yW|@"OM/ʎiՏ r*}=UVE4}V:+eݯuͶ\b{XV/ث'|WV~Vء<; OV\__ OefFt-~$)ғ'vN#!bt)Eԓw 2j q*7JCQfkO{ M|&"^&fRnX=mlUqendstream endobj 785 0 obj << /Type /Page /Contents 786 0 R /Resources 784 0 R /MediaBox [0 0 612 792] /Parent 775 0 R >> endobj 787 0 obj << /D [785 0 R /XYZ 72 702 null] >> endobj 238 0 obj << /D [785 0 R /XYZ 72 428.3182 null] >> endobj 784 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F42 469 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 790 0 obj << /Length 539 /Filter /FlateDecode >> stream xTMo0 WB}KCv@`nlԑI'[rbF"G$AE (Z#@+`1H KشNq.D@I' AɫI4${Ƈ l7-"KiF)=#Ɔ0LcVw9ܶf{N`kׯP8VBɀ}"20%Ϯy+ۍ3eendstream endobj 789 0 obj << /Type /Page /Contents 790 0 R /Resources 788 0 R /MediaBox [0 0 612 792] /Parent 775 0 R >> endobj 791 0 obj << /D [789 0 R /XYZ 72 702 null] >> endobj 788 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 794 0 obj << /Length 1733 /Filter /FlateDecode >> stream xڅXY6~У,OQ[$m(cHZlo%y;CJ2XKp曃b?iiʣiCa 32wfb$~Տ?(1A:?J(IUfogDE ZeV@ZA&Pf3ũ"<iFBP#pEtVImAfBus"u:^$Im!LHMR!7G;Lhsjķ2*;! Q'||H_]lY88 /)Ǖ[a[eTLHaזDخ/Vxݵ%_NSPcIy,7X<=Vũ@gnL8?; X_aq?-C RK ^!z,enݛ7v{QS8w#;n; wr{"Lǿ\.ӕ4˭<@#ȕ{9aJh a@ЂPCo )^n3gtj y6O D,{x糇gwmZ<|A9,~vxdyăA<7m}ym3 n4QN䋡/:[X5y_p1чRS@>1Q@ >]cY_5rޡh1<S$,:?SERwvpvɿ.r6{#;J{Zt^Y2MwF9r΁Ox޺E y<9k|En_*RNsjVu% P9P`sA& Z]>C!p?>șJUΫ%d< ~+` W ךVm"Im{RATe$2m|(Z>a:`m.vZ3X~@G\j_lصeuiuvy V7 m0R'~sK5l%v+dna`GWV0{\X5g2rjд6;")7aAp޶dyOSȣؖj%ߒmxHqGWTMb훅P`͓A' Z] O9RՒkҾ<.wn(-\dB$25$M$ HN. 9+F7Wq{v׏4%$LiԔJ <%: P` v5=S 5#PF 1?J))TKٶ%3PW.Nys/p~>zݨg=jQ}ٺK ݣl}Q@!Mс=Z+L35n6\QnPvCw x]D`W685,+\ Sp[$yaͧ/4ڃ݆f`jL6{6m MRjl÷sJqN$I!;N@g]ByՎd[zFt:`?9Tendstream endobj 793 0 obj << /Type /Page /Contents 794 0 R /Resources 792 0 R /MediaBox [0 0 612 792] /Parent 775 0 R >> endobj 795 0 obj << /D [793 0 R /XYZ 72 702 null] >> endobj 242 0 obj << /D [793 0 R /XYZ 72 680.3998 null] >> endobj 246 0 obj << /D [793 0 R /XYZ 72 375.1431 null] >> endobj 792 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F32 324 0 R /F15 309 0 R /F31 314 0 R /F51 451 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 798 0 obj << /Length 2058 /Filter /FlateDecode >> stream xڍYݓ۶_P &Hžvf8M;mOqxORKW볋@PxϜ@`؏.`N_bb;f~XqK3U`C ;H<_Vo?r)3'($GbBFՇ (L%]DHR&gFȩRxl3 t{T*t>RM^_#ef}^?ZLksme)l|bƂIu ó}<>Xnz[SD.tlyr.Prr&2ﻍI*6;J#9W@̦T21M ~iʔCF&]Tu ١鲡Bk =Ž?q|㆔]oN̔dZaUDdD '_6:Q>lñ"p4լ Ǧdl9({qq#Lr kbsf#d?;Tѡ6p*b3b*)䶊3C ˩mO A'W\NkQ=29= J*t<s_RK>ѯ56)&x9 M'pD59+es@Anc3e4C`)kH(0 ŭT99I,BmxTX.rн֒R +LX8Agl!Q;"X2'{KGcH7v,× $:$5T,e_7y>@XšZAk mpb>9dK\dPчP5! D`UfnC{0`e|SOȡ -kWR#sɋ]|r߀2*&X@Z@- u+u6&R>v{XLe6u1ll> J4SE,|H嫫~8[識݂R$;) $}EKdzhIHy9ťu]C5arO3+0G0jqvz8%SסCCsz9uؕRۮl綩]|^$.Q}loNj=5I2(6ҏԡU,/EKJf9q>,R7gVLdg\W=vJ'ENH Ed2o\2*KX˄Ӵ"]&W3$P2nuGxS<aQLoB t28.cҠ}6=}"x^=vXvsrcr (b#읏Y9OB]D 4 \4cp,e { .:qHuao3\:w$,]u5p琏'Ob7n5$bT !fm,ޓj%ޱ},WY Byyܮ>Ž# s`Y^+'§Pi+B!z\z<ڈp,\O QCT*@d ӑ.@ V~*)I򄮏=;; "nY8e@QY3;%߉} p. 45\2YTI33\3{JY#+3Sl!I0ihH/9@p%w쁬[jhcJfwW gu%(k ٷ훹1L9CʸxGV D̞ǀ1hr*Ǥa?Z1+g.ͭW:9]Ar|r7~ͯ{7=xbx#ݽafcMDxWZ悏3.@}_cbs3C<70K񩁘co"T4|?-Vr݂K %/g_8LU~"c{}1u9Z.<6V-endstream endobj 797 0 obj << /Type /Page /Contents 798 0 R /Resources 796 0 R /MediaBox [0 0 612 792] /Parent 800 0 R >> endobj 799 0 obj << /D [797 0 R /XYZ 72 702 null] >> endobj 250 0 obj << /D [797 0 R /XYZ 72 589.9669 null] >> endobj 254 0 obj << /D [797 0 R /XYZ 72 394.4459 null] >> endobj 796 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F32 324 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 803 0 obj << /Length 2005 /Filter /FlateDecode >> stream xڭXY6~p2+"EHEAAkݦsQWޤ@a1gR-eqr,o`䗅`i 2  4HA5XAxxvR~jyuRj{xehDoOxz1IQ,ǒNU^;XIc?Tw:2ާ|۵i7&[}^,wE4N |&\(qo=s[( Rj: T׉Wd|Z+ŹJ(U>|aW5:oh/GPyEUTWdlP#=Qؠd: ;|tv)sE*I5Vvnjrq&v<9 (d̏qqC48ao&9$`ӽ!-ecٱ1 $1㘬R£ d}7Eu#a[ @M,;?PEg8ER&^mC.C6\`x_Fk`mez\)oOлCX  a7ϬxSr(r:;P搷sn~hY0#̩t` k24򡈶'ći]+YّS8 aJCF'Ʊ6/ђiA!D\v˜\1b\NJTG)ws׳Ўm!Pr/qt&plN~Ol}\T'8Q{ҔR~dXbȻbD3D%W=dN˗8dcFHΥIGu%Nehw CU^;(?d*cVӻh# \$Jo]>K|ܯ [!H~3nBGL4՘d BC(NS?RhdsN;~.Ju=܅rA}Gֱ} ] y0KeDzZ" Z !'" ]a&4APjv1|^bIGi^ P3xd(O.kYWa w yivpOch2]"9RTb U]h$}rMPlgcW *Cw{.*E7BYuVaR> 4EYtHvCA`47#R{ރD(? )]:DzmM"zUp <'PM(uLp@tEi[\NhC6v4Ii'=NNM3ٻjendstream endobj 802 0 obj << /Type /Page /Contents 803 0 R /Resources 801 0 R /MediaBox [0 0 612 792] /Parent 800 0 R >> endobj 804 0 obj << /D [802 0 R /XYZ 72 702 null] >> endobj 258 0 obj << /D [802 0 R /XYZ 72 135.9091 null] >> endobj 801 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F51 451 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 807 0 obj << /Length 1624 /Filter /FlateDecode >> stream xڭXK6W(k.IzCh/-䠕R[r$9Ey+'AQ,$Ùp曑U OR=P_)##db2 :ٯDSnV/ UٱDZپ m^ݾ͜)&39DocfTe"O,kzj3='L\ǗFtʡ.|a `6OR<˃$_V~XnL\#s*hnH/:†PwP7@JMȜtTz[ IO'‡֍{Ϲe@[}Ѿ/⻁+*䚼 qNi:3aPbkO3)=(]רHMTd˰jԟIP1|.xxɏuEL9ٶ$ژ8DR[VWx=8m'Ί>^N_@;J>2љUں_zsd)-xҦ/Ⱥ n1OS8Ik e'D97e4&x[.MDQ]~M_uSnbήpvyFKYzb-Rp-Fb':n:'4_VHCPS(.X;^ JX~ݻ ӜnNm$Ll&Z\z83pVG oHE8Db ȁTѡp| $U7B*h /"(] ȜYRLHPCلv"7cxîƋLY TJ>+ ;Oa)$^\ȁc MB4M9x@&t*D R"ܟDPu?v D9ܠ gꭚY_%w03A#@8Ɨ(s\yҮ>TK7iQ':m6/se_D\3;kHItTwɊ M\c|۞7qt:fhY"E%$н7;wzO2QV&8ԃo$`yc(u_]EC/ ^WGlV+RN\%Ze{//Ȋn8EM{iζw˚KJ喙壮#V93).]puzY侬[uy dUjP3ԋ]"8B͖'W]L]"^5{_&qNkJ~|&`L GܵW D_07A*r}*E:PF_! 0Ֆ :F¸}FKS׊P3Pљk&}YNcml:oUuGXLn΍J˿cyrÝ~&_&J}Gg:l:^]&>;^B ɡdgH_{bmS+_ `endstream endobj 806 0 obj << /Type /Page /Contents 807 0 R /Resources 805 0 R /MediaBox [0 0 612 792] /Parent 800 0 R >> endobj 808 0 obj << /D [806 0 R /XYZ 72 702 null] >> endobj 262 0 obj << /D [806 0 R /XYZ 72 136.7293 null] >> endobj 805 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F51 451 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 811 0 obj << /Length 753 /Filter /FlateDecode >> stream xڥV]o0}WD mljMͤNӴ-j"4L6]j}$^1E8{m#rCƁ 5]`@"91Pu /[89.AE*YboӹOLPHD"f-¹Xh(,`k2KzС7 P O>{.V[讄K-:`1w ;ȉnM? }@(c@kA L{KgD4 kNtiVpNxͫ6C a[S7qK vtHb[Ezq\N6Ӳz> endobj 812 0 obj << /D [810 0 R /XYZ 72 702 null] >> endobj 809 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 815 0 obj << /Length 1333 /Filter /FlateDecode >> stream xڥko6O1D=`aCY5ؒ'Ia}GT`:>Qy~"/WgһgaLu8F Et$fvV%HKq7ͻ'ʅεHqnF1y.Ljro_ұ@\8M&L*]*m, PBˈ|'Aw3)#,LnLX~0LhG;#Oi4rnLS#4.WEa%~6 Bwےm=;0 #V"Ia(.+"n׶.VŮ>簛fce;1oi-o "GM96Jde #. B2,0d]*g{92 w$jy.SUH:6HK,xN5c*6!o1W9u;zy]XU q.(l sw`$9sN9ꄜ<>Jnj2HyM;!A:M舦u;;;-'(~OLl/t%yնڇL.SmGAT 2˟K$T/*ԦCUQYRryz)YP1vY^]]I9pcL9}ᡭ.b <.氚8!۸=XM s趓Ne瓹='X'3`xh)8Vj%\,pu$@NH|aytaINhVp!y=ulb.Sv%AE㝬sfu" "C] b^1׺זКIKEǶ9E\;/5ԳSbLQrKe]HNjXlF &¤ p+*b]4oq= lp3ڙ$15}}$~"QL?ӟ;]~wHcAw=u$SNќØ n ,&Z+4s? i-=%Yha^ͦ8I&" suJ|?M_=endstream endobj 814 0 obj << /Type /Page /Contents 815 0 R /Resources 813 0 R /MediaBox [0 0 612 792] /Parent 800 0 R >> endobj 816 0 obj << /D [814 0 R /XYZ 72 702 null] >> endobj 266 0 obj << /D [814 0 R /XYZ 72 658.6379 null] >> endobj 270 0 obj << /D [814 0 R /XYZ 72 176.0247 null] >> endobj 813 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F32 324 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 819 0 obj << /Length 1299 /Filter /FlateDecode >> stream xڭW[o6~У THQ74ÆuXf`bP$R'K$ )Ka<| "iEʳvJhg) U275hIN䅣w[Xs/fQ&hY޼y뫩RX%5Pcf n&5t1Jx|J%H Ȇ<:% \IϞw+ (0\ĉ_06z ` <.GD00L\`guk'a'GnIhQJ4M梛t2.T\/Ջ޷&YK1TntؔUe/gáӡTy߯^`)o۴:(ri2xifKHVys{Q%I%s<=.UYWC1͐-X$^_ʫ83^69ZXZ^}q'1R REʴx^f1n0IWC¨{9]b.ڱ %Pꌇnɀ'\ {0 # =؇ng~FAj]8%hD9[?5_endstream endobj 818 0 obj << /Type /Page /Contents 819 0 R /Resources 817 0 R /MediaBox [0 0 612 792] /Parent 800 0 R >> endobj 820 0 obj << /D [818 0 R /XYZ 72 702 null] >> endobj 274 0 obj << /D [818 0 R /XYZ 72 197.0402 null] >> endobj 817 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 823 0 obj << /Length 1055 /Filter /FlateDecode >> stream xڵVM6WhsD\$!E6EhC$(d^%עwk!%[)Z`j惏0y)Rʽ|=-XX7C=Ah"# (”&DQżyMe&C$B FFJ%qa:'JiP?.0:7ػMAO_W@g*=|P•Tz&T_f?x܄]0,(.c("U6M uoP0huk.3@ͳ)*xU~Ɩ&=^wa`7 E5߮xov=%$*I;}vYў`qtXx)(N g.q)?n9endstream endobj 822 0 obj << /Type /Page /Contents 823 0 R /Resources 821 0 R /MediaBox [0 0 612 792] /Parent 825 0 R >> endobj 824 0 obj << /D [822 0 R /XYZ 72 702 null] >> endobj 821 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 828 0 obj << /Length 1060 /Filter /FlateDecode >> stream xWmk6YdE\n9ZzWBrxmm⵷6Ŏ8 P(%h/~^zn2b' ܹrn'0BI /dc%GO<龐˯WIzendstream endobj 827 0 obj << /Type /Page /Contents 828 0 R /Resources 826 0 R /MediaBox [0 0 612 792] /Parent 825 0 R >> endobj 829 0 obj << /D [827 0 R /XYZ 72 702 null] >> endobj 826 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 832 0 obj << /Length 995 /Filter /FlateDecode >> stream xڅVmF _G5UU|8io?@Z)VU{m@ ZVۏ= 'Xz1^vp4?opO3X$~m!6a{'83oYb?ǻ砄D"6?4ILdov}Gy*mbfZ9FȆ6; z{9,4q]`Ù4%|6űrXjD;\hċ"ôh7%؆2uo?О.ڮO(ȳ1&}wgu۞kYi( pn[(j#v_y--cޭvaƲA_wffRJlYƂs{,j^S;Pu PtBf~[cf9m.}8+ngdk I)wdySҰXDg%,= X8=ǩ@M((KwjrL@&~i5IW.4ȍzmC d_5lW&JfK5@"R *[yicN)/#ߧy[;Aʑ"HBdD1ڹxa|ʏ"ao ݱ6NӅۃ]^=a:ım` qe01Jp P&vBز!ͦE!֚T.{40Ţ&QHM8`J)P0' m;nBGTbuAUTߣ::-caҹ@J ͔$!Q 2?Dk4 CC ?TњMIWC,{9rl> endobj 833 0 obj << /D [831 0 R /XYZ 72 702 null] >> endobj 278 0 obj << /D [831 0 R /XYZ 72 462.617 null] >> endobj 830 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F32 324 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 836 0 obj << /Length 2090 /Filter /FlateDecode >> stream xY_FH_ͨpi45 PlZJr{H]~4!9$7$#?&fƢYx&XU_/fEe+c5ԚyX_|󷷋WoTF:O֑Ts c+\ө2;0tHJU<:jz\'eRj2De*e\Q"TkI<3'h ZsT*1z|w@]lWDs)['tǾ=_{E EWW!GM=O,ER:cA,!.d]TyJ1JR!|--BMq`0gN˟e\dY1mNpL)4##lgaͫأݪ& NBټ!\!o{40žj۸˛8g\eٖDEYpKR.NkgCS2 h!TC&Q5x<"?A1=pt:y4 }RIe?rꓔ[Rj'4ǧ-7MX(m7z 8Apkş"; p}fQM%I{X̴m,-8|P e BC̳{,!:=Gvrt9"` C)cِU}d1Cir' zF^>m dv~WFcn's1?%xI3!i<8C:>n/|~qpWKRd&ԦRWw4CQ]e?(uTI&Xf '~'׹,> endobj 837 0 obj << /D [835 0 R /XYZ 72 702 null] >> endobj 282 0 obj << /D [835 0 R /XYZ 72 680.3998 null] >> endobj 834 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F33 327 0 R /F42 469 0 R /F34 321 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 840 0 obj << /Length 2622 /Filter /FlateDecode >> stream xZ[oܸ~2ɢHITM][cAi<5Tx_s!)iFc$yj ãsb?IMF"_/Y 7*y-H`C :O7" 0P?^}Ts"(2BܸhdI7/[syJ Daf_^RKJF޸żcu .;yFݕy-2WMyz RT}s) ?_Az/ae:.TK}9>@u=m$ŒNﻲ+_EԐ7pʏCO iCj(WQET-,e ?3%0 1 5̛rK4}縧{SݖwIӢH<3q`B=4cEtv[м2󪆟mWU⁠31YuԉzQ>F0(x\k5 C"o!)'(mb-ۦe;JEtJs5\a7E?ع}rHxgEqmd_(4WBA{e:1YޙAc4)LGY췏0B\hƚX(e=e:R"f9pG S ӴܶD8بs ϠF@5Fێ/XPUXYI쫉AկEؗ )|: TUڜY$hhp~cRVE0z18;T Xc1\XwT⩬&om=0)"r<̂zK b'POv6ñ.ߝ"( ިX: z @ *r_]'irdcD>\0 BJ;Dh$t //3;NX8L)>' H@QJǶ+7 C^Lv-]&2s LDd8 ? Y\R~qsVBV3%x6*VfqnwMTЇ@b~8BīTqL_4%4 *J?+9 (jL7?Cc @rQ$-'1T* +X75 BAF5,^q"P@ ԅ)(I2A-԰ERg(A#yE@Yn+zJO6vp0!xwi~կPM|^qnl|qYʉ85縪nĕtv! u\ySAxe7pkG{Z/E("A*|/p| Sp ߍJ-ߘ\/5_-RǦX S!Lg2gY0`񧗓Yh ♿PA,DaEQ"¿u[͊)iX6mH.hAi&RuRwH2=LОendstream endobj 839 0 obj << /Type /Page /Contents 840 0 R /Resources 838 0 R /MediaBox [0 0 612 792] /Parent 825 0 R >> endobj 841 0 obj << /D [839 0 R /XYZ 72 702 null] >> endobj 838 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 844 0 obj << /Length 1917 /Filter /FlateDecode >> stream xXY6~PQ5@ E6WdHe[,m%9$l- "9|spHϑH9Tr7F~yfF:ZP<'Bt `dx1;'E"ϹX.b~}_bcO)f?_tıH$v;E^Xcy|BPm6_/n -GF/h{nl2kA@xBKE={Z:+PL b:R$NLg?:>ys@6 =!@hD tn sm1`>Z%Eo ɘp # C+sRL)rc.2tU'66vRjI3 Ż2q\ خ3W /ΒO Sȭ1txܣ Xklè5d<C0%:4^"iiS쇛uQdՍ8X۬:[u);?wNRG ;4$<iQ3]vVr*E ќqlImӱ4BHʍ(]|?B,t_pyd`-C8Kń=)v*ul<'wQ"򪞉*n iiö}H!P9{7tE(/vtPi\;BK\s`tX&Czq5'q`9/w3_*!uۑÒEv^N/iWX-€yGJڶۓFD:>*~ǸΜRY)qĸգ^ ?Cn` X)AM)$B0sprK>5|]s$cс/@x=?ǧϲl ${БIu NeCP$~< !!Lt?))->a1b 9@4|$<@߲*k3 _S{ .,LƖ/.q6LrG90+FyWapR*ЍLJٮ'].S4¢WS;7cl\z"x sTQL@[0LQ1q,dw[I{W)M O>MਡLȐ>N-- Z?Q 8P\*Ox %>p[%Xy endstream endobj 843 0 obj << /Type /Page /Contents 844 0 R /Resources 842 0 R /MediaBox [0 0 612 792] /Parent 825 0 R >> endobj 845 0 obj << /D [843 0 R /XYZ 72 702 null] >> endobj 842 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 848 0 obj << /Length 1883 /Filter /FlateDecode >> stream xڵXmo6_/db~ذfźؗ[R*Iw#iV Y wyHß2e\FGW u&܌NsHQ⬞/fg e]Yj"Z>v,LnU93ԸUuf/a) Jm<چQ\wSyE?#+umH].xW}ށfU*@ |qI?6ޝ5HM݀rCZr9YuSW+r !]qޑNNƚ]붡)Fun`_d Lj\AaSoo44Y>| qDLF@:S^1r;";["،KawÒA Ȑw{|ʡ:2NrᏎLQ&r; oNR#K[-= 'GSc*OYDѻRVMF=R;[j:2=r_#}/%OVZ pa<}7OYLrf9EڠsȵN8<z\{V)ߐkxrGS}T- KnU`XjL37.a7(p =VqK J=¤=hM½k|]IZvmk]vsG#@f9P!Ts .Ep0 c KjXkv|V.ټߊ7N9(eSė])b .Urgyɿ ;k+.F+~ ]qOw {˟ ΤP=zlwV c[@~{q_v<ՀޥH5>NX4':QЖ&Z 3|]8Mzy]B^@a3 I`L‡ᾪMLK-柯^> endobj 849 0 obj << /D [847 0 R /XYZ 72 702 null] >> endobj 286 0 obj << /D [847 0 R /XYZ 72 680.3998 null] >> endobj 846 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 853 0 obj << /Length 1843 /Filter /FlateDecode >> stream xZmo6_/d`f bС(JeiHJl%p2Ȼ{P K(PgA[h" ҆6B _zrpQcm%J\\7gl Y"t%~Ao0M#m<=pUת?$ G,@6 +ҿ!K˻*Ͱe: Po@`i2#rW4 (Q^(κd6/ߍ;X8JR0Ԧ"RIt"|[[o!kضYgq_PN4N&#&JQT:Hʼ6d~s-U*On;ᾭ2q⬵aݶ<%B vDJv$<-؀S_8B΂M=<I'Cҕ/Cp ƒC"J-LږoN=ウ'z|}OĦU S*C(?ŸZ(Y.26a*9NN{F*(q#ӳ@}с&0`C`SuXNP}9,>N,4 "Z1, xHAVమ?-xDѫi.LO'To q۶Pd^x-9 }!@pKe^ms)~>=[ $nm亪7h4iYؽqi,+iC}BRan4]w;N@Vԝ/`>e{Bk" 0rp_J*Ҽ:m>8Aa!Hdsd=0,8P8 e)61{esb=DyO渓D؀ Iu9dh%:*a&jXgUmؓ-N֪7W5zkd2 U|3`GOn y%2 Zd@%bE#5Bə#p4V7츜4 hoW̥뮳 A r%Z$p#QFM;e>}ݱ (lIX6:k4ʏ-nŴo:~QGPttWeG#_ŷ{d^EO v_:&?.Ct2еޡuajz%ɬ\5gP<%> endobj 854 0 obj << /D [852 0 R /XYZ 72 702 null] >> endobj 851 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 857 0 obj << /Length 723 /Filter /FlateDecode >> stream xڵUmk1"_]dGPbJQᗶ*nu"{'ܙۖBKvd&33 2N?dV0m VdP`ZL750dh䢶& j<&%!&uu59=:*9PNyox?هq呆GwH҃BOi[߭uUcyQjdlVt +߷h?navx.eEW_gs:iA{o lS(v7O\6e,=eQ (:G V>Gh;s EN;@zS轠 $;K? N UU GXZ,r7Cf`D\< >;ieS6@#1S܋>iOSf?HRo a{2˦+﹞C2Q`T02C Z'!%׼i; gjБ)kO[5'ӵ}4׼y`Q,'t{uS@L]tisLx3d;"oR緑œi35qvwq b)iAͫN$#WÝ3{oy1.Lqcj7Y/R+0!@ %S+J~qgTQӛ䶇&ac% AE8,V|*:endstream endobj 856 0 obj << /Type /Page /Contents 857 0 R /Resources 855 0 R /MediaBox [0 0 612 792] /Parent 850 0 R >> endobj 858 0 obj << /D [856 0 R /XYZ 72 702 null] >> endobj 855 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 861 0 obj << /Length 1435 /Filter /FlateDecode >> stream xڕWێ6}WQV\/I@ZmH%ymy-Ԗ')!),k-vÙ  ,1<1'& e 4O N,6R)J.Y??kD9bJb4bf/)NV{AL&8UɦE@Z]YHdRKBtInG6#CavX-^eFx&g\% à8s:am^YΛJ.)Cg,}*ęQ*3.י1 !QԄlܦPY45|M̲`F0v[]|a!o"j\G_uɏ;#vFWXZ7Ū8j  d@Q%'wg܄iݴ=PtU/WAAgG >NA{ c$VFx6n-ݩtL'G8m^o:H~yZUDxUV`Sv&=ȸ@UlVDG ]2fgJ"#0UއpO癤:\ >1KJ<u[>qJ8:eU,%O4ǏMgC| "*Su'L7D f10j;x~guu E{Z٣F0z'nh9Bqgolmqܥ@} x/F~~+SL[1Cp`1GQ>_ݮt<2SL54M%Q5]"KпN:qCG@% YC^q<!$̟\OZV*۸-E뻩-m+Fls2Nm 3࿝6I5@ '7:o{ԓ'wMYY|y@U&oVL1Lͳ딗Yܗ0+ ?܄oU2 L01|B\S<Ӗ$ .m}-qp>0GvEoob&w;gҗ XkMz=0~lg7dfg7C V4{cև-td%-1x6I~{P{et~Li ߓD:C B/=yendstream endobj 860 0 obj << /Type /Page /Contents 861 0 R /Resources 859 0 R /MediaBox [0 0 612 792] /Parent 850 0 R >> endobj 862 0 obj << /D [860 0 R /XYZ 72 702 null] >> endobj 290 0 obj << /D [860 0 R /XYZ 72 680.3998 null] >> endobj 859 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 865 0 obj << /Length 2107 /Filter /FlateDecode >> stream x[o6+Ƭx'nmyPb1۩M^E831yx.) %Å$,Iqs`L{HHأZ)41}5..5..o]/^rv5_~MY*SLCF/Fb؍RH ]Ah_JӮV?nլjf)Ut /&S\ycV`{8z}\}K)b5!j]fϗwm%,]wpVZt qEɋx*1SC!ʴxHĚnV-25C}WŌnmsV`zNƱ֪6Ouo}(SMT+.~2$Vu 10{~r/@Fr5%\hs(Wnv;9cB9 1\W'b?RJon C3|;*Ƀ];㻟8NuG!Bs"_8D3# AvQj^HB}դCJx&x(y)TE*PgzZ4vW_X' x^M,`HHt:$7Axl`R!LPŎBK D,t9r ҙYϺtHǐJz֋t']OaۀAbASؑLIz1%~s{Lo"([`aE/*H\RsbƈlӷUxn3@ !4xHKDS?^ـ`e(Z\#s#YM*"Qar?f3j8bs1d?ެx0ycq_ܯYۘ[9PWC __Y'wr:ĩdZ4燨sMQk sD̀20m:Eiv֖]@^lf7Vh@4('*1Rs bƦ&ۍJF;cݰh^Rg'}!^ilpu8O5Ql|i$ɰ?QQCOK^. J(h݉{&>LM>t^Lp{jCeB'?(> I&0҂hU-ϱyap;H:PD2vC0:{a Q ZB":ŠgC bG$%2-HRmLؐ_IJ&FK k1ޜJA@$ga{%uӦyLSXnZ/}GX)3StK2;]lE !|hFB,C~ոC7 tl7fe kr ؤOl9c-yp}V/|fOO|V`;>bQ&`Ǜ9n #U%սo#K1PKm]Hl_'endstream endobj 864 0 obj << /Type /Page /Contents 865 0 R /Resources 863 0 R /MediaBox [0 0 612 792] /Parent 850 0 R >> endobj 866 0 obj << /D [864 0 R /XYZ 72 702 null] >> endobj 863 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 869 0 obj << /Length 2111 /Filter /FlateDecode >> stream xZYs~ۂp4I%U7xW6YU^?@$$"*>sDR@LO_K(aቡ<'4;0&P-3hQ#3CuKzrS $9Ko.z.W eDf25H1uM\Yt,#D1͸scSlED&ҿOYZMg,aTU;|?7Ls2")"i=MJTn#\P,Op8g{`':&>iJ2mr$ y1N3&VFm@FIuRmD-IepӶLۖt̴kP@WB{fTۍPmL0Bex#Tc07Lm,55^HxݣytZ%d?pt3MfY݄1ęA(bf=hP0 $k;4xl!knᔖ='VsP+@ZuQtf$v[;'!9K?|ru2oo߸fx6y_OIo3׸G<Ԑ 1>ݡ ++vsSADp "@%]u)V'ta@]1dQZ8`rg_s1\و%9Ҝ0h.ÌxaE7=@^ۜh,1 y6P6Z>0!\I#:`QXUv5&ACYxFHQ|5_*@u!8t{ a '4DAQT@Q^vaY6 >vO:sk+ #΅A2wfZqs %4F<֐*'%D|hlЫ0g/9M$Qe38 ć){-wS-wJwYxON#pn,Yoxt꘯~yJL\p|h*2'U%Z~7iMZQmKkMMkI8ٚ .][ӰnQ$&]MI8/= _:\ǚo'eg>Ŧb%snO[bLp^ `0DbxSafkpLȟ9TҙяPTI>e>c s^vo5*|&Z4pl߂1}Ja "4=>@pRA.B#qT+Scw6?\}S* `0x{]TE6^wمГ\ ~7oXTy:+sSk0'@r s"0iO3+g s!pڱW(-e2p#̴㦇q{[~ۂati`N8sdY0`/G`#8גTͥv!`9wڰ Kqi7].C;L17=mzDoFe4S.(E{pt!d.ƣM$G`D]b<򁸿b_oRlZڵPK5%`e%Y`#Bi&Q?D{PF9@ C]0dCbnNcu݌^.eF|IBT2Jh?-)c&R ϱ{d1A(2=#=،?¶>,5P W1eRzn}`m/3 K2 3^r*Gmf |+bw6PΉ2t6_/ alfj2 o ]hQe0VX1v }DDendstream endobj 868 0 obj << /Type /Page /Contents 869 0 R /Resources 867 0 R /MediaBox [0 0 612 792] /Parent 850 0 R >> endobj 870 0 obj << /D [868 0 R /XYZ 72 702 null] >> endobj 867 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F19 306 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 873 0 obj << /Length 2010 /Filter /FlateDecode >> stream xZmo6_203$u+ n5ؗT[I&r*}#%8)Rm"O=w'XB%'dz3%6b MJFLTHF&DS>=c2aXjYr~4W7Ϟe"&2DaaOx_cU$1M'-ѶQ"6G[cP ])F  c0Ѿ'\R2ـuF*Qp"#9c- 3gйf%[@}ʲb,|Q7vc#TX\a i嘛",^-5GG d}W ӹqoh=„`t`TLo<"ںgMeɆN ƜfKoap&?{Mq-\UEG8Zh..ҿ/PN2[ O{_#E_zu=_vZ9M,"6ŧz&ds g:szv%w9DTgg(V81̨-ot?dGZC@ dEKO&D4M/Ǎ#P&=C$m&Bn%}uuQ׈8EW"^f2Dzg juژ\T?Z6׍yU4 ΑVB/x8*xH{L=RP6M&IV>/oSa<}64¡2cIfK@-MDiEerFp˚rw+tSV6ԧn`zy $w5ŅW \N܋>1NW}\eZ4.%IНX3,rIvӒR6(k/!- >|I7ARB0D[JJCtʎb-PγDrV,+8?@?$pٟfn';L"8#˃d<񃻂631q?ғ #k"oyOT򵵂j%S 2oڗUNBtE]Ӿ X<#a`,8Ό&q8x@4NXgh+v8q ;ǮY,]v(cAN_y:hӡ@v$#.}0f XLߑ$0$HV}7CrKvA8xFBrKv$#.}Pf X(J+Nȍrȁ մcYe/bDX=t6Ȏr̥(wB!k.@$CtnHv r,7<Y<3KC9KY9*9Jts$[aڟO\(mZ=z`H_ݧGȆ[4kA> endobj 874 0 obj << /D [872 0 R /XYZ 72 702 null] >> endobj 871 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F19 306 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 878 0 obj << /Length 1872 /Filter /FlateDecode >> stream x[[o6~У Ԭxam-Vlc.ʶ(GN |&yRI*$CIdv;J;iB@7*G5lb̃|iS RӋE\ͯǯ&޾|Ip"d Z!F?]n8 =Ks>;TZkqd|Hsc PDLp}Ut\€}0"%j,Yfl̵aj2g孚Orvu5U/ia&S5k?S>.׊3Xm7f'TJhC6?rcO)A rڧ\3}wz>nLCКez9T@!Jyk?=*Q{si/fdL򾁟G|]әOLhJzaØa~1-kZ69Qk)@!ᳵ!Pef })*4f@+¼mWC+Jl]PR/E4rdV5@9N^i(K y^쒝`2Ɏ(;[vැnP$S+>q1ִd< K_p|ltH`LkSk\uiH%~V?TRu@`sp7Јx0{@1^Zִ\gIquyẇWlt)yr9˫V*w=Um5m~e.|!sL>p_au"%qci@q|وLV/6>pNP=_ ⣪tQL䮩튤^zʌep˓O,)ydJgڗ,x@ zHܘFDBko!xSR-!b bQD^2XT`=IAN@a^pVfy A}Y eMK@T}9 {];2 cHukO#Z+ !j$gW4r MtE8JV +P-AZ@=4"fFUtN. q*.Z1JwAv/6+%x52@XvJđOW'\z>'Ogq\U%RM!4Zַji~5vb㝌l exӌY}vEL3"׻`GX'2endstream endobj 877 0 obj << /Type /Page /Contents 878 0 R /Resources 876 0 R /MediaBox [0 0 612 792] /Parent 875 0 R >> endobj 879 0 obj << /D [877 0 R /XYZ 72 702 null] >> endobj 876 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 882 0 obj << /Length 1919 /Filter /FlateDecode >> stream xZێ6}WyhHmoI[kko%;wxE6FdQIp"I"3LFYr5k2mC**-aJr)tLx៯F/^a Yk;|zeBL?hѯW~P.r#UNm}( bP]ޭ嬨f*:cIǟ*(ռ/n$t}%<1b1&gc@7 \ d*OFLe1z7cSĄj'ȗaշKbK.)ʥ eH\$U\PJ4v,|ط%"Gd99/= rc0(c9OQ`p&GeRJȾC=|$Һba;9'f=]ރ 7벶F]k 9׮qcxK+S5repW̗0++[v c/le,3 Пhsrlu)dJH,QE#"p@4 a%lA8h$[4bGE0J-ʴljzezyA{7Xހ؃0D: 'F[8IĈ$ `M?ObKTنz3՜qkַPr/~ڷ}|g+'x嶬\F}M斣 Gwz>[gPLuOJ6Űì#E@c/Ir5~}mōRN@ҵN }jlE6OUګ Ճ}j< j:m5Lu0e3gE>^-ޤ*lmŪsk*.ֶy;ySj;,Y\H7r .{IdžyJ8ܓ"v8}vhO&1Ӄ ح0VċLQ"d@L:tn8va $NCt2`e[ 'VF0Hh$Ts&"kꅥ:MDd@S~A ;BhO%\]/P6Ŏ$`ĕi ԦKÓ జ1=pNk&GB2gg`߈pS r?Վ \Qr ൜Ϛ$A F8cDc=Te]Nq@⣹]>v;G>qq5,s ދ=hi{WS,Z­F-YL~ej3aEk<b\JMUlkfò>KqXq〓,F"Q#v$(vw[41u<yBtrP4bƒusgm ǴE&xq/d.@`Lb `:5l^E q*8W JNl& s@J`ddiي&sop'ճHոe(?/v$Qbh+m:^jŽxH5'bXmĬx6T!Zټ.>-6iv:&A@dT&K#4#tؑ F7L Px!%q! ) 8VC^,XaUpp.VqX G`u@Վ6 Dvd bmd 7ܞE({ 4cXy(ۍV֥QC4Ҩy^5qB8r!=ʼc A nr;֟nEf@ho bR?M-YG{V,;O"Tendstream endobj 881 0 obj << /Type /Page /Contents 882 0 R /Resources 880 0 R /MediaBox [0 0 612 792] /Parent 875 0 R >> endobj 883 0 obj << /D [881 0 R /XYZ 72 702 null] >> endobj 880 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 886 0 obj << /Length 1172 /Filter /FlateDecode >> stream xڍWmo6_o(bk:t,4YR*ݺ_;%K ;1 /S B;8yQb~RkKGMZ+xfs֛O[Yfsl[ 0!fv=Rrl0#ւ;- {eY[A+ 5Kaarm-s rō˦: x*ϥ䅒qH_x"Bp!̹Rg /^ )]$fE{Y60;]]UWT&mI2,-(dd,HYk܁tۻ&c-jܨe"ղˮtw$F4O$jE0Z j36p?'dЫ$Hť*B.ՙ@1y#6cs8<쫛KR:.._6_##YƭPnmFCӜ\B8 @]W{SXRcB'r3_"'4H H2I?rX!CC J@@ov )؞Hd8iBHW$AoUŸ{@'zѣh ۷l΍]]Kن0s犛4](:zj~$0*lb/sIJR\g:25H%Cܜg@(<+mŘ1h*H06 ":IPš/N| =tW$B+BBǡ&.pT p:23})g=RutΪ<O Oi|1=Ϗ1=ؘ@Ϛ2;B?5FZW*;VͱTdts|MwrPJUZE6z[WGZ޶SU_qd Zm}Q@X}3`κlhIz_Zqx_}~J(۪endstream endobj 885 0 obj << /Type /Page /Contents 886 0 R /Resources 884 0 R /MediaBox [0 0 612 792] /Parent 875 0 R >> endobj 887 0 obj << /D [885 0 R /XYZ 72 702 null] >> endobj 294 0 obj << /D [885 0 R /XYZ 72 680.3998 null] >> endobj 884 0 obj << /Font << /F52 445 0 R /F53 448 0 R /F19 306 0 R /F15 309 0 R /F34 321 0 R /F55 489 0 R /F33 327 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 890 0 obj << /Length 1694 /Filter /FlateDecode >> stream xڽXo6~_@Ő)-Zۺ`:t]=yPe%1f˙-7 GD}❾xw8 Ae<˅pOxUJX Dثwg\S Wg\ݐZX>_]_)R>(e*UD D,^]5fҔؤorXDoJ)4i{T0J(J,3=^oLqikk3m4xΤIM[8o5'is8qlRox'D>~ WqT-ﲕL_A#ٱporMyK=NRC[EeMapt5Fȯ ,<5?C^!]w]"MH@4, :( }v0NYdT40땉X*R ֠6Dm6P<&HА5ȅȪ'W/d?_K z%uqMKp  ϧwY'3J{(rJK[Rd3&9*,-Z,F86>`l`s[l([V+c#/{uWP-#\adB9+-ӣBNԆvPl]!TPs̸}B2 ؜̓VenYe*K\OY{/ +qHxF|%EzUFTDSy}r O]fEB/g-GQe1SbZ+ 7e,\p՞pjEEi,ԚQ%Uf[1>deN8Y-M, 3@8A¡:Peuyu2_144'-lr-e]͕E[- H{<|W7/x7"*<|V YU%o/ :ֻTrUw ¢ȫ;"<5<5AC?f\ZB ])CYG:Wxo.ۋ(V).62kH C)n\Ygň/wc f 6;F鄗7'}kæx!&ȝQWw[w#%IҢn/CJ L }.MNJ%:;4 ` K:1]*zF@aendstream endobj 889 0 obj << /Type /Page /Contents 890 0 R /Resources 888 0 R /MediaBox [0 0 612 792] /Parent 875 0 R >> endobj 891 0 obj << /D [889 0 R /XYZ 72 702 null] >> endobj 888 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 894 0 obj << /Length 1673 /Filter /FlateDecode >> stream xYˎ6+çH.Z$@h:Y%Yhl-D4KR)&m'qsy$DDbl ɋi#rޡa^_pkb-qڃ]<'"!iIr{XZۗ7A q5imOҩV4y݁0Sq07UѬL勼YfpOGsydD{l! *7QtrXTu7o8BhJQ$n̈́'"M5~^qxJD3-0g*spnƳ$cOځք!u@S µ" %iw3C4Wh";m 'zmõ 0F NB %Ӌ Z!y0;J8`͐"&x4e8T Yh&Ly$yj ,Bl11:ج1‹c+bݩMS+ȳ3|Us{twfqcCqRB7a&vԥ7duvx?Y:+lHK:l S&&/ + &gE)qPH*vY 17_4O{vd4Vl-l\fU U K{lVE kXxnbtT-B9=t}$dW{؜Q^)kP+ڬYM/ˊ1]O1s M2E)i"/+aswa[JXZ& W됓$RBn՚t:K ^ Vl4bҘKg UN&0&:~OX+ . ]6gf]F·;v?>5xjXCt`z\ ZV\;5ېzj?ɡtOيƋTԘ5lY|w7bgdge~E"~DasbD {1&a1OBw|d)E?Nఝ_l'M;hKլaƋwl֯m'xO^40,'}@L6|5dHg(tI"`/OXiCʓ̲qRieXW *McIaHYXH%2e ȀcxcyWfVm)^NBMŬa%)1k\ XOe,UL5oyѣMu!M b*uYbƬWT ˣ,܄ef֒ )z]NbMa|@D6'juuz"4EnlQB@o/ =Ռ='5=lV{oc+hSwl̟!E`!`O}@llv1ˬǬWf=`egNΊe%vA^p=Xzw89O v:=hVy,+$lWVHÿ"_IhxJkڛO! hxnʔc3?©)Ne zyvD )dg 8xR:{B!1Gendstream endobj 893 0 obj << /Type /Page /Contents 894 0 R /Resources 892 0 R /MediaBox [0 0 612 792] /Parent 875 0 R >> endobj 895 0 obj << /D [893 0 R /XYZ 72 702 null] >> endobj 892 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F20 313 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 898 0 obj << /Length 1451 /Filter /FlateDecode >> stream xڵXnF}WP~I8A4E}pʴ$D\]^Hբs{83{ffy(`#4YlG8Y +8K07>`bG7D$# IK@nƯ&77Aq ش1nFF4=uCV~<5]qnU;_u92o`[f  L.MP6m!$IiCisWA9R5ޕhaS%F (.:P#l7r}@(N )5Hy2zo 5l(M{sb9lyEtmӔM$ҸsAm}DJo=W8 w+pLq"0 ap=$C@`8FZqr{Xf7HuNWfs)D* W`phaˎ(DTR{0XX`Gp!!hh=k5q.-ATzomZh^K/0pn3i\,Xek3BVMK"!kΎێ|ҏ h']A P1%4ApaORr|~SIhvPݜk9 c$ M@8Pp~c!b-~؍x`RFD$L~@qP2؀xi˴Ag2pְӶiicBݖ^ (fK $aDȴ8 6sz=Ip&#fa;KvپŽكW]?e*'лa,Dȇ2ˁX 5l0 {g2z"MNoeCмf4r 4C'[n@JDxÓ`tw_A8|B͸+H(X 8Cy Ú8-w}XWgUS~2(u 5+u H5q!T#o8u`+`5*[^Q=1( W]n$\]n#?e+F\&)MR IWZ*1L3_ks"m4&ݬ]IE=<ڏeő ;)G!E4;1Hw,wХ4rg sbJ~2.>D?5 FV-S8xIyH %R-,U@126endstream endobj 897 0 obj << /Type /Page /Contents 898 0 R /Resources 896 0 R /MediaBox [0 0 612 792] /Parent 900 0 R >> endobj 899 0 obj << /D [897 0 R /XYZ 72 702 null] >> endobj 896 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 903 0 obj << /Length 1504 /Filter /FlateDecode >> stream xڵXK6W(5o)$mqѢIW~ c7hif8p(P$IFyNhVh" 5a7f bQ]On^10J,,/߽KO?ܼ 2DiA&"^ br^1XmM5yVT%Vۜ3ad)KsxfǮAnOHʝ>O}fBInMMPNN~BlKJR X%RRTG,JcYַTZ*K%NmCnItN5a.+uRѮV Oz +P_k;%<㦭x*{tvxuXOSnO?oϥ $G8<`nOatgK0n~t,nju]wإ7̀ү-Aؾ,hf }Y8'@oJt92Qr64LZ0?.` LL Fp%6jXl\UXFOk<6ZZ~ ws$$Y?\y(4_U0xhӻPz1:Cơr):t\V-(_l+|(_Ma%K1vPDH#2̾La./Eq?_̿2UL@UR3EA ?X j #Sj6Lp 65fzZ4]%!4{RBABxF &PUdzFlU,#LAVwSMőa#D25eI ^A_|m1Be. K77As~(1i,0|N!rlnF*j gyZ8a4endstream endobj 902 0 obj << /Type /Page /Contents 903 0 R /Resources 901 0 R /MediaBox [0 0 612 792] /Parent 900 0 R >> endobj 904 0 obj << /D [902 0 R /XYZ 72 702 null] >> endobj 901 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 907 0 obj << /Length 1739 /Filter /FlateDecode >> stream xY]o6} ?%X][ð6$Bmɑͯ$Z]E#Q<<"s <0kxzF\s#.mAŭ`U|=xEĜ`"eq+}D\rcj1{nhD*Rr3uM^ՠ=T+ܪ?ZiKHM=u 2s"cj仝}; #b9FTI5?x$~~vW"!@E qU;]rDLhlwDҹ?^Yϝ1V,)ժ"i,T.|S(Y+C>ԘJ##AX+ Wis:xDwG!-hE\CJJq~!(gm?~0?%dDH1f\i U(*GQ='ⱁMţ?p87=۪?/^2S:t]D4t{~047t,tXцй#1N@:A:$=:}G~zk6[=mkґ! TI#f N|¶ FcװI[{a}V!?<Ê{1kؤc=ְ>+Bq.@+aXÊ( foEGqFȪFLo{UKۣD !&RrԮarzXÂ(߯}P^cb>vVcװI[{a}Vt_oېwFD=F̟R]]3j3ms_Ry2mѸTN opPz}ؔF Y.;cEҾ\E"z W9SqHN~zj[U%Em鐃dxca#lc ;gEȥ_;^uWN SXO\ GPw)Ú{VҖzB-#4R&٥1PS#!aXÒ(/$'C}TlY0fÛSM* D6T˥]D׷l7!|:+3Dm]GG]2jv+{P?y 66aX3#mŔ;O, mIwbM}tV#@d<5Y|p@mkϺl'PSf >#r$QᏰ6䱂Sb4'$[2֙a=V-k%PE*$_RЩbûѰdD0j)8POendstream endobj 906 0 obj << /Type /Page /Contents 907 0 R /Resources 905 0 R /MediaBox [0 0 612 792] /Parent 900 0 R >> endobj 908 0 obj << /D [906 0 R /XYZ 72 702 null] >> endobj 905 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F20 313 0 R /F55 489 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 911 0 obj << /Length 1519 /Filter /FlateDecode >> stream xYM6Wh_C i4At@+ĖYwH2eRZ$mڔy qAfty`"N?OHV$Zo,KX_Zz~vq$\MQ#=H %#؁0Sq(ӡWTe˧EU4+,k=<:dD~ g .0JhBގaR±g URFB(9Vf"M,"Qv_)o)pU euĄ+jH2fUkEΎ6  g+ɍ-E4GuYʪ+;x9Ћ2>U^;Ř@%MzJc˽Π&۽9uPuى#ST x( ֕DLqu0")n)$ :PKL)DS*(#v5$n ~IYjyc^~ V2-!6Y.UFK7D^H" S;جSGGa}V1oGq9.dz{)lV)£#ְ>+j?zK$.: Pe]ٶn*( fanޗf3z66aw1I!(lC}άVZu[ΡDO$q'x}ȡTͭ6;3b&˝svENԱN)vdܬ1Pk6;B>|@6+QS3®*Bqpz ^hY=Lqb9hzY77u[m54Op6Wjajx_v.[ $ekˠaCyԝo9nm?zC]eUїձ X4ۢ?_C8tlU5ۏ![n;6gv6t:?9^ۖ)\Ias÷wbY;i9I|S;جSGGa}VB 9`JqU|54 WL)`OYƴ+b{AQ^nyӼo}By|XB2w>Fڀ?˂]?HF{^ND܁`Tl>zþȁwATWw +h7X)`.cRb8287Or(ݬ "`A%H(v_Qe͞.X/pi AHN?Bendstream endobj 910 0 obj << /Type /Page /Contents 911 0 R /Resources 909 0 R /MediaBox [0 0 612 792] /Parent 900 0 R >> endobj 912 0 obj << /D [910 0 R /XYZ 72 702 null] >> endobj 909 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 915 0 obj << /Length 1393 /Filter /FlateDecode >> stream xXmo6_! T,_%t][E,0/YNْk+͚_(JDKݰ-ؤxG`#AL /ppO^.HKEÅ "qԂY/ " )H- byia ]D\r25gX<_jD*R2p5 M-hlc*eܷ"V!|2+,eA}\ jP aURW[9Eߒz9]18 H!αBAŲ,!;fo*ٙ6U˧>nˍz0$ñob)163NɮY;P|x%E3wO>ɋ [nҲ8UIQt Ec䵨pgeW#hyXEJOfFf/1EM&Dš aKzVG`1<~L& I92ܦT!G -dwIzI@"x40Q<4K1$ЧЂBJ!S׊ty4O&Tʈ6 ={LF'cC꥖=ɟYlB[aP @HC+AA=;HbiS($3F'wS[,S ;GZܻZ5R n2wcq:Y6 S6Q6m^!s}YUp)w!+ydZ sS䙂QB%iU!ԐVY p^Јzl) 'L'ql@J1΀~ݒ8`kJ-4;!t hфcV$Xv)zIU4Z^=5z_WemE6fI%"OƒX/ ń)`O*~WկmOqQя8QGJsz[ԓra՞RP _h bDqsj;ؓr#>a >dEB0~ Ç"VMBG ɧB'ߞ~aAHZ=j:| +7yW'L'n8c{*g 8z8bEBDZuSg$#r:jxS<׭{e~5w;Yw*z)HIc–NvȒ%1;͙O˙Uܶ)3/pG$y*`OΗ3e:}7_LU@B%dޘYH'_C @&_HGRx!L5[=[otB ]0NUgshcY٭/Q\2{MmVa~@>whw2Y-l Rg[kξr2j;QVmSVōF>Z4m k%{Byg-/bC UhC滝ldY(+aU @\BfUn4lWW()8E [bE4ӂGEUgŪWmnaE%w~xˉèV9 YSV^W7M\٩\F}خIlF\P';/0D]oyYIT$ZƝ(ҿAmNv:,xHa͠Cvˡ>inA Au#tEuo 8<V;QJKE#qyjy}HӝqV~8pLș 7x9b';(7fG0BI},QZ/15(endstream endobj 918 0 obj << /Type /Page /Contents 919 0 R /Resources 917 0 R /MediaBox [0 0 612 792] /Parent 900 0 R >> endobj 920 0 obj << /D [918 0 R /XYZ 72 702 null] >> endobj 917 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 923 0 obj << /Length 1528 /Filter /FlateDecode >> stream xYM6W(1o|T[z7wiʢMڠ@Hpgf?<+(7/'$Tҍ vOWG L b>yzT(1԰lr^Z|&nn饐1$l"{DL̓$F2=<~6V>{MWr[RsclV5mr?;߳cS3 |*(PoX_O>@RkaJ"9JB{5-0:^߯҂R{ꨭ(+ t3g^zj`FPv*vN rjm!8 4: 94hԣ4F Nkl p"4**(7\A}h ^)(QJ9> endobj 924 0 obj << /D [922 0 R /XYZ 72 702 null] >> endobj 921 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 928 0 obj << /Length 1454 /Filter /FlateDecode >> stream xYMo6WV?$Mlw=$@G޸pĖII,J. 4CǙ'9QQʢhv7gn Pn$xccvtM0$I >NAF@e)ӛ)>HƘANuNLKTz8S \-+Wf qp{ ' 2KF7#JNU0tt7.O:d')q!?I4v"\$af 4' x(AքL53'}|@BJzIA"%<>7J_~;Qbf2>.S&g%0*K/BțHIvG{/V0~V͋^͍)sawjNXBf,Y%Nqh43 M&)$6ڱ= !w.IT%)0Y%Thr@6$[V֦ǎ]JcrC?`VTXزw 'p\>Tmȏxg+㘥QinO <)ᕭE-m9LO.5Qq.*S]a^qkۨ=FPa)N[1g96f|͇A*ؠ } 񳾦 0Bn=@l{[YôYĹYrA/VM䷰AW2OVr^YYl{}!O4ygWvJ}\O㈕Լd|~u~ޒR!e>8l5⛭RNPaȋsZY-mX)ӒDNA|@ 5lHބ AAY_2D^OQ@w}/L>Ogm7Ռva.Ca,r>ʰ(Ԑlxzaְ6^g#^Ko~(u^/8]ia>3x$@4~`y?఩Ոo6B@h"h2$h ԏ-h;kYoSk ƏJw'9\(C{3..i<O 6(O_½> endobj 929 0 obj << /D [927 0 R /XYZ 72 702 null] >> endobj 926 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 932 0 obj << /Length 2563 /Filter /FlateDecode >> stream xZ]۸}_aoئnE}A!Xr&h&m,dd{//idUj{{ qO#,yf! 7a^ I~OĊ`"eqݛO323`LFܼi )46yӁ0SqV.e<$9|&Q_6c;15p-^n0*V#2:puoُc/^I?0 @6J英R*9VSx:!z~xwT&`«bIDx&W+% aHpR9p%p"BLtFA"L)%E~w]$%\fW"kjC3Xʂ/!*%W _W\zJbx&hzvJ!욵DgAxRC4K^SN 5#9V'Dw-.F8n::\ƾ|<ثZ$?VBC_ٛrhPOt{ 1|Ž{)?6ݻ GvM},z֜sRٶtҥN!N92\40Ԍ.7^D + j"vҾ"#`+$Mkra}{ҡɓƎ,ޞP% ]T1'RJ97&2NY# iG\ Ye|@DLWfTm׌$k(:MH&Iޓ I,iH8y ϷF,gL1N n >\RN_ZރX4E__G7n}?NJ6J@/G0BDZmFF JbKZXҴ)n8wrQ9FsӾ!;Xafb ۶(2C;<ūC-km1e8X=Jx.$_ju=e-8[k3s,Ȼi84ټ &q[8F8U<#HW"Z;RNNl>_=&uyҞ?6lM ph=Cjz sh 玁NPʤ .1!\&pYǵV[=9L!&{f|VWacKvkn\~puc^]*kL7k FYO!ɠ$Yi:<@L(YplgEi~ tX_K%JWN$LG8,_TlQĄ5ϊJ[t )E׭em"TF^/wg :eUv3ganu}e+ ya1]jQ۠2,GyK a)h_vm3Vnp'h{ն ~mWiu+u^hO}mXBO$-i%EUbE'SEsO3r+7 _Aodnk55H?'Kʠvd`Y&aY|VjٯT6Eo)ssƮ*z6$p2MX7Ef2~YX[ؔ2 (St[1m:آ61A kX۬r{+z۷.`!34-6q拕j` d/.:O_>dDN[66 緝pqh 2 NJGiz[)F$3$IbıDTHbjtE9bְ >+2\Ӛ734˯E}p}͍gL-u&X"yY1M:آ&1A kX.ċ}JB`^Txҭ"z RL1լiWVwML K©HTQ$H|@D$Riuf۸_|Ǣ ䷒Gz1fY2OTrO)=B[xleeρ) a'SPQ6ׯcixyH$&_` D Zx4ǛO k|kS'98:I5I'sZ[tZppژui>kJLկ)Qbg/oE;iftWڻPt,4Uڜ0\ Mh:%S>_}@l1csT΍\Xbz~|z9O,htF߻mOPaX!Mtfⓗ&&yNg,%:9'gzg6=9C0|C/"IРy3Bs<73z#Mlv|5KQoͿI\;>,<;wlašÒDb3C݃V&^i[%wl|J!u"i,Ѱ"X})89?1uendstream endobj 931 0 obj << /Type /Page /Contents 932 0 R /Resources 930 0 R /MediaBox [0 0 612 792] /Parent 925 0 R >> endobj 933 0 obj << /D [931 0 R /XYZ 72 702 null] >> endobj 930 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F20 313 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 936 0 obj << /Length 1563 /Filter /FlateDecode >> stream xYێ6}WQb.""f&Ev>(Zm-Ԗ_I{(Q%%i mw[93H&IIL|3/pٌwpNPaZL,$N)()F,o^OA qS5bvlhBig:wy@}8Od׫8_0gEU$[}x8w̉ 5n3D*Ut'TfNֳ;` Z$I8mK:*RD L5%|N)C(z`툜Jp/ws1u_c_c"@mvaa,ѸK\||y (bm΄ ƶ\\0[ 4m߳vwؤWfM -!J Mk W5.H >gobSm?ε1NŰ`LkzպgEUԓ4\h$kc3  "Gb9 /.xke;'0Hm kS5ۍ>ZPH)!aIkJ[:BID$%M&a=pR讼1a䟨^y7Rۮ>B%4aŲF$=uul"i纘B]vZ)nj MI˲CHXJz mp qw5HKpfPSYέsn)eƸ &+SÓcu=gpL!]ċwfs.|NeWE5а a B;*?vBgsuO9;sL+X[C 6g +ٻH-MJFR }XTl2*cmTzZ&D6fp9dpXY3$lXk0Mj=Fjc krKuiFI8I?K7w2:eS/^T*Sn~:ovzMy,N=ٜ7Ѷ׍PH0Æ!v'vCT%H1:Pgm8=`a)E QE|XDl2$cmLz_J< 16t1lR1VkXkf[B' qc$T6o{58[mޓ䡟 (IAKe0>I$"$g U6I`ϸRYn lpiAHe<7Yp?[¼'2T >Ì0= 4AKSxw 2j{g?- f # AO=z` ,UgQJ= hMSʜt9LrB1l!#q$^BMٮWsXr%iwY˧l][kQ"EY S5˘น'_hendstream endobj 935 0 obj << /Type /Page /Contents 936 0 R /Resources 934 0 R /MediaBox [0 0 612 792] /Parent 925 0 R >> endobj 937 0 obj << /D [935 0 R /XYZ 72 702 null] >> endobj 934 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 940 0 obj << /Length 1542 /Filter /FlateDecode >> stream xZ[o6}У "v0 K<탣8[N|i}$u$JڵhyGX.I0%4ɶ•R G8C)\=hpshb.qZ_-&goHFk,nKX\4xwqW\CAL5RHZ%>S c>J{wgsXgds2ݙCCvLqL|qr }z7HhpJ' OUu\Nq7!sFȟqu3\RV!y034C(+PmֈJڬw'rsXΌOwoo6V>r*R{+c軬Yfج}|Q w~2?jy2ɍ:#O Ώkwi&r6Sk8?QHK"%xԤI]#g~0)gt4ͩFẇY`#װ1ﳲ-Vtc4 ܻ-FSV0ny|ᄽ0åmq("1-J* \בPӛ0]U=;rjSCBqpxpx+lԕaJ5ϊ7U ̚%/܅;û^Vsxf붨lm%1"21JԨWƪ.e)ݙI&W4Uci_ROu?* (&jXfӹ #lYȂRSzRŌљK:8WKMck [, aLM'Ixjp;ȋ%RkiS>k;>OoɜpR',Ӷۇ[aZ9P #. + 6Z1¦(zY +:X6bܬ[w`n xm2ndƇ 83p" _{sJO7fyr%VzkEϡq;pÅBP_Ɗoo8zXb=ܟe4fMu_@XЄk,O}p8ֈ'vGt8q %j1`uk/`58[Q])T",QkxrvmwfW +=R:-(ax+n\Wjؘ+Qڕ>kЕCD£ N1+ب1FkXk{Avi|I %췒-U{m~ "1T}䯺ִ2mm1t_هo^=1ZG_qyw "WFʞDU;:'m᭴ZN"U7Up(uۘ_3)=TNciܔͶ&MD$2 b`[a /Qendstream endobj 939 0 obj << /Type /Page /Contents 940 0 R /Resources 938 0 R /MediaBox [0 0 612 792] /Parent 925 0 R >> endobj 941 0 obj << /D [939 0 R /XYZ 72 702 null] >> endobj 938 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 944 0 obj << /Length 1668 /Filter /FlateDecode >> stream xZmF_ᏉD}Jm%(-U&/"qzu9*X{3;3y.$DDb,;& G8n ®L%NkS"ƚ$cիOA q54 briB:* .]{PB*5l{ٜ)>}.fpM<]:dDԆ NV FBKFT+'P Ct 6[sh$RB~Wne"uu  a.k4-VtP,fp:/fTOMGO `6> aYaNq^_.yq{N(a-@N ꗧze|6odN8EJ)L!ں}R$F/0T6ZCMQtXE|eCV]KCQ 8\#[{q;yVݭݦ.?wwH>(RS+ċl7#ᖱDɮZ8P'm G5BZ˱Zƪ%_-v}XOٌy?)䦜epg6`WM2?L7-ΏFUy4{6UY6}p\Z;1xQ:4*UD~Xq\#-ێ|XGE:*jh m3-oH,s 0ak<+!A,s<p!`(]6!&]xB֯^,33+`: ĺzu5bserSB* -!¦(:Y5KH>uNynuTRCKǪ,qe$'0&Y]*FL3򚩖m V>V 0ˊy ]D156kX5-7Y1.庺e>@yO =K(%Cp\v׈{#()([G^ Mq`o hj~C4NoVPV/u NPS%~l8gl $l~ 210zA&_Rp ?\endstream endobj 943 0 obj << /Type /Page /Contents 944 0 R /Resources 942 0 R /MediaBox [0 0 612 792] /Parent 925 0 R >> endobj 945 0 obj << /D [943 0 R /XYZ 72 702 null] >> endobj 942 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 948 0 obj << /Length 1691 /Filter /FlateDecode >> stream xY]o6}У ?::{HjbԖ3i]DI(CKC$df l 8’k Iqw-!RaYY.^ 6$[},bzs@LxaUM52,fvy@0SqnUWyd_eq\ym2?SCnLqL|̮>l}z3HmKٟ?8{!5$x(THi FA_1P ,cz*-BB4jrCZ@#fvaHM(Z-`` %7m! Yk,|ܖ^?oKxJ| #VUs~\xO蹣)5$dcؤc=ִ1+SX`)x4Lt+h+mU}jM8Aa#6au5ůN`EJj*JjVErAjC )ņdI{icVTA~2-j]Eܒh3Qc/[۽2!1JqI33Wm7Án< P168p.{̄\X?|YZxrL _Tg?lu-> o|1̡SLx} N{}x׷;\J])aSɎ 'Ϛ\-E QQ+h6/%CJ 10ak: 1*]ERM~{-B{]1ԍ#Z54̈[?VV(; *ʒ $ sb8Xƞű8jH;rtM.â!ųƀxpVQV55$I(03j w XyIdvnC 9&m}0SeM-8뱦=z;yean.S02?JN+/W1\yb06)a#Lu@Tlxwtь%A)Z['$T26dow&N LN5l*q$YbE;OI* fh@OueUtܫ6/Kl3#`Cx:MRi1l4ƄI{icVtڲ-Y#YR]hm z+;L-a 2`z6zXzǬ./sZ!"DG)PoBPfAE%I{KUa0glGԷۇSj#vrb$v>>%jԔ OkڰZCϡ]{[Zc?eս kvYUןH {2i N{Zx;\O# > endobj 949 0 obj << /D [947 0 R /XYZ 72 702 null] >> endobj 946 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F23 952 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 956 0 obj << /Length 1559 /Filter /FlateDecode >> stream xڽXKoFW(nvh+ֲt(Ү;KJ( X8ow8C%GEi¢jD Xv'I~(XFwDi%MI ^KƿL^ri"0 "btFkbQ_ӡq:*! uo՗bYObqs:.q>4DH ߏ}OH& aFh5Jw|t;s+oB.vLw\vL "1[l …b-[|;Y:b]W y1az\N!΂IYNr" 0 )QM体hCw\*ߝCOBl1l\Tlimx; TRR|\=Ob;m H| U򓏞<0qki!4S-|P޵Ԅvr& '3 ;б8aZodbұOaF Ƶ/#֬쉣U)#n8r}sF;#`N(:3}$`tb_ p<;h| hJ밽a(8+L{Qȇ2C·+t< ySpy~,x4kOo:1˙]q8Mپesc}[иvM;6kSv]R!?7Dá=M9,6C컭Ȼ]փ6z`/j](By~9Sd@w}vxW}^t _tr :h AŹDK}yVJ{ZIQ^Jm?"%\+ږjX:p޷JeuKy Pe6cGF[Wre: ɈV2=G0G;ǐGZ|PO蟠nJfbeeH᎕#aVZɣ+B&GL -J׀nq||֭t ׉Ɖ&0?8с gZ|/jwH5{Ξ%$Z9HJMkɏ?a1jM_$ҁOe]#Oޚu2DP,05YފrȜ2R\4$K b)E endstream endobj 955 0 obj << /Type /Page /Contents 956 0 R /Resources 954 0 R /MediaBox [0 0 612 792] /Parent 953 0 R >> endobj 957 0 obj << /D [955 0 R /XYZ 72 702 null] >> endobj 954 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F20 313 0 R /F31 314 0 R /F55 489 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 960 0 obj << /Length 1968 /Filter /FlateDecode >> stream xڵ[o8)yE7.0;vLglyh،#Ė\IN6&QEg ĺOyΑD<0\s#(Pji>v+b3~~O9cN[b,/ֿ~"(CQqSZ]Zޭ;,Co)ӡLs& GQáڊrx럇.DO[Trۼ'EٟEӧ7գV8T}׶n7gy>1^y[TBkvDVսwmG vb+iutpxt޾su֛|-ͩi`Cٴ ʶ6BH6.;Gv֊T{['jz孨E)nvr;NQ_d(FIaӕq@h#T?=oj;GvQ.uƙ Zǽ[N^y[~= HU^ CžB~neIȅrى' %4\J7 :U}s^6ںm^vZ2r]7Ǖ(;QwA(n ;[>f#lksy?T޽TE)69J2'dcIJQp k#'q1#~Vnw#iQ:?|;,zш <%hE9JIQ$1YA]!ƣdޙQ~3XGuPbphJ*ErCJj'ILا J8MI$cWLbv'\?_|P( @`pLMg7lq Б>79VO [ͷ$JYʦa9!X"`k`%$}qHA%PA^ILp 4:K4@u@.̽&Q`LgP huovǵz8h%8F(aPO1ߚ]HHWK%i*Ll"%6_x: 1fA{#U?W:Vj%ġ6Eo cix yePK,"%ş~ZwO'+J40 ̚]쁍T\UtPSJI^b|ik6R%C%SDޗ)f*Sd:!V"`jg媢zJ0 g2.L-B=A;cqM^jÄ^FՎ}ŖAXsV(1fY{V#U?+W姍w>d,)͎{lsa@q(kvHH2RqUD. # LQpVK ♗MW AGgvGP1VxFMQ4d?28P;VY=!NүUAokKhݕz%X2u""$p ܚ]쁏T]U^„--(aYB߰c% JFk'0P6b@ Sg3oN ƳNW~A5#$y=0@xi$3ؑS4 DŚ]쩌TT\Ut+_w~Sv˭x`/a'qp؉ٝuhX*a+@g&"<DŽp\zp?UbΓS:~T$N |5ÐS[ߙw4C.7zoW!(ቭ>>{ދQ}NRoUif7s_og G tendstream endobj 959 0 obj << /Type /Page /Contents 960 0 R /Resources 958 0 R /MediaBox [0 0 612 792] /Parent 953 0 R >> endobj 961 0 obj << /D [959 0 R /XYZ 72 702 null] >> endobj 962 0 obj << /D [959 0 R /XYZ 111.7576 365.7521 null] >> endobj 958 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 965 0 obj << /Length 1956 /Filter /FlateDecode >> stream xY[6~ ԌHZ lɤ-zKIdV#K3A%BDI<.(/-~mAK&&1p=ϹBF.D|to?]IHbI]{B Y)D}V3#ZxeWmIOmp#Hr0.:6 SLW"eЪX`ԔGʾaɒڶ~\3J3+MAN# aEٸ||6+a+߀5,_=a0F/(GЄs9u2)\Sy,shꧢWYc)UTY[aT'UZ>e~dA; jZfVFW>} dn\md戣]QHM27 ]< lNIF!kP+SϨ!Ih"Z}?*") Rf"l"8las&.cHI2l4Ύ]d=-FzGAbRQZ&]\-9K٭֑M rwSr{جSְ]V85NnL@x׶x/`Y1/u"jyV7N$U5MV!= 37]6aǀ5GF8DġK/" I`1 v49U& UAUzr DTx^;}KMLT0SZ-e?g7q C\)> endobj 966 0 obj << /D [964 0 R /XYZ 72 702 null] >> endobj 963 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 969 0 obj << /Length 1862 /Filter /FlateDecode >> stream xڵmo6S I8ڮ a]f/dʒ+qO,Y .~|8I$ $kr3!"(5P *Эۣn&f [˻ǜw+*W] (EQq?+]&Myt=V.Y].h23kfc)žn324?.6*We>a )%I@޶vAɄXL4! _mH4ry<*oVX"X0鋺>olr0Zc;A6ك2;,V^@zY<]=bm~*Uu}6r鯏؉b dz.5!e.n6%lF7n FG˭l:3o5`jqSd2,Z6Evd\bٗ6r>{Ӯk9hܲF6O0UYyg6ef6dN\HRU{hҎ&+6:;}3#.Zm }_JL~H޲ 5חηQ䀘45Ynlܷ{p&s[Q3ӲQ)2eQvQ m(T4 cɴd 0t|y[Rn4hoisZ4QN€& P!]nO74b_4UnBݩʶOQ@uR搄Ռ2("URQ1ΐJ<gND > (%) W}rhBӾWN%! +3ul*ȯҋ_}{Z덗TBXuT\1tZ7<2 gO=y).?{b(ńAqP t* * FNC3m8aiVБupN5=y!FqXgهXnN5ֻ& 3=TJQD#ڨ:z՛zb2blf11[3d8'F%/Aendstream endobj 968 0 obj << /Type /Page /Contents 969 0 R /Resources 967 0 R /MediaBox [0 0 612 792] /Parent 953 0 R >> endobj 970 0 obj << /D [968 0 R /XYZ 72 702 null] >> endobj 967 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 973 0 obj << /Length 1993 /Filter /FlateDecode >> stream xݙ]6+|i5#~IbؤI-$Dgv{?$ʢ6"!):'lDl9΢޼QK4$Ej~#1Buv+hbDqkvs):3*v~^qDBAh-Z^޶2iJTҹt3s_JiտNE\T,^秼ZEtQb%"b}g?F-YDJ#s=YAg(!v/L 5TZW8c`uee \ߘXh% p#5]fSWΊhWoR]aezW-#e%ng-4%EcܕI#i?MjlknOobElЁ"l1<<5V~@6}~i=3SLE."%MܚXB!5ښoMC`S%%q pG%$&= L$]Ma^lR%w~}gK|ͦN TPc`a:gy4̽`0`,1;.sD"2 5$10 4azc0$1@5 WĿ:2d6ټ= -8 Nࢸi`tA+r5(ɮs 8:IcǁjJ4w/jTAPT*vBDb$#vdI ί} 7 $t^|SX|AlL_裪[] K:9` 3d7&AGM}4&tiJ}pbdQ$ 9IDcjJ&{҂zs -.* PiJoұm-v7s'kHUx-^A|<QP5 x :IY/rc$axxJ3#& vDa"*j0)c~dϰQ(^M6^EqqX%G}zRmtwo8FIM:ue$v%uc$d'}9]ӘM{_s `ϕMc,$1@5W?")UkpO5PܷYпhQLȧm shL?7?O1sO:glϖK$n%MB-rI9җRD!g $9endstream endobj 972 0 obj << /Type /Page /Contents 973 0 R /Resources 971 0 R /MediaBox [0 0 612 792] /Parent 953 0 R >> endobj 974 0 obj << /D [972 0 R /XYZ 72 702 null] >> endobj 971 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 977 0 obj << /Length 2029 /Filter /FlateDecode >> stream xZ]۸} "%hd4(<G,M$ˢ,(P=eeJiD"Z lDKr%C#m& vfK! >h޿_}ū (lJ%bqpD"evycAcإTCZzszWyƫ !5&hDT>/ӏ1x\, pP./TߐMLc ß$Q~xYbA&GzL"Fst-:Yу h.D3Ā HՇE"̠g-exOTl<kFghQ6^riq0f1Wgo+㹐0F j"55rY c]!.eZYu}1LnZCڧwy~3Tk"8fn6o{l&JHbxCKډ`RA8!PM7a>zx =T榒koz*X۩4`jSkQw=aJ<;j&be&T`BH`QƖ-I`4 ޸h56&Q9c.0¬7t̫Sh | ϰɪxԃ*N7S7@J鴀 $ "tY=m'^"ȪKxHC:.e/C=0LBYج|!^_>L}ܖňG6oku?LR= ٿ dPzy)8j̳ƻkV7kY󒆇Js'N}Z2Ԫ:"P'II@H %Dث2bⲢ˚es /roWRDpLLwv5rY2v MY!=+a'+ uEՊԗ»p"0M+dYBL#VL.+T?}Jp8o_THWW~X{>]8:؜:A‹:cV:Vdw#X,X*C%+ r,)[U]}"ͪ1od ѩ.վZGmUՕ* Dua O. $͊"EEvYQU+")y翽*)!$^NsDsl7)l[ATW>= *߇0Y1lה~)^ m&b_!ZHӕ )ba{MF~Q\2S}M1~VWJhP2J0 1ݍD y!O+N~Ե)+auPҾgF*\%/Afendstream endobj 976 0 obj << /Type /Page /Contents 977 0 R /Resources 975 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 978 0 obj << /D [976 0 R /XYZ 72 702 null] >> endobj 975 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 982 0 obj << /Length 1983 /Filter /FlateDecode >> stream xYQ6~ IQY.d/-Kw.(7HωAvߧٻt~QX?%\I5g"a?vc^)UI>t)"UtYϳJD=g|N* I>w d죒h v.c Zئ&8$#2ѱxOCb%j @ns\zf޼,D1aHGK1#2=' t4BM\!_heh&b̧=KzOHOE<"`0؄ v?h6JHӡtJPٷCеN4qph(x3s޼K+?)&3 DH.2 \i=?#M);8]6<ִ,?<-91??I9fyءp(tU*dѼ1O6Ϛi:cJFB@~Y.*m5߮wcL).Pb(8sV&f1M:|̊m}'e]g51Mي$MG.ݟIGf<.q\θ*a)9_]G=0;=ńIWF&pdEj{}c-3V;NLOv_%1-O}U~S\U̥2>Imސe !v$ea S*4:N)'Sp9nd45vv||]D إ7~ QYRT=PA|n^B?~|K槄G$< L'6)f:)6& @զ 8G 59t0B?x3"ULf.6ؑ6@梒tŵN9`GA3߀m 9(=3oz7LDKN/!"ӊ]s sE5>M*J SX8YL:^/ĔCzdETX`s3l )7[n<@E%z;CS[,GH74QJԃ.%uC`@SRٛ@;s@zPImW< (suV"wSyT?{.*9`择as 9RM:~MϥR~? LΊ]n nE%uT͋hp%F3[ gJ*—Yb1{q ]TC=23Ϻxd Kx Lx$!*XF(VՉ`Y,ɓ4A0RGsbsQI4ޭJQ⛕ihf|0 ʜ}M&NAQ0|ޭg/vie;7H\'Cv$bp){?(@$T}ڷ鿼yI #6~ G6xA/t5 {.ExIfjSem@T>&l Oj\).E2;6~:\Ԏ$|JPb-=(HȘALADPCs̤c_n[3̥kDpa٫~;zajw_}yL~me {+񐡘u4ヨ 9OQendstream endobj 981 0 obj << /Type /Page /Contents 982 0 R /Resources 980 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 983 0 obj << /D [981 0 R /XYZ 72 702 null] >> endobj 980 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 986 0 obj << /Length 2130 /Filter /FlateDecode >> stream xYmo8_6P3|kd$wCj-)7XSp<$s dy|| onf~sp# Tuʭ@*A#~vqMĜ`$$gb%7. EG\N%%1o`@F.ҩ+'4.o?^X7IK, լN c"cm #!h02lƃ=gw7z7$y(L (Dc<!&y0oh?SO$HD]}@'A9YJDCQѳrhL B$Hl$1гP0eTXDX "ꫤ&J@RPP'C(kX@$y:c9I[~HȗUUZ8&>ޢ ƒ!oRCM\|cץ!yZD7UڵbЁR`5 &ź3sVk0hI@+b KTg3~. ҹ(E`1ETujxE=Ի=N4/**]{2+t l{w3:@ƅ Ģ7 q«C3Zj LT8kT3^I}Oߛ E+a`Z΍\e&ٿZMZt4K<ei~}L5?dXט`*|^1/4n,6?{{Y_OCeO=Ii|=~Mt ]_|kU^vgeUO{%Yۡօ떼]?]E@UZix;VUQ@rPa|inzȞO  %WF]?vHn zHOe\wV]8vgz-ޙ2C;Hw_w}O;>?%ei nb' ݭ"O,DJaZ:1EpE$Rn!f)U6pw/CVCf$(T t0ycCu]dw\QsQ'IHMq4d8U)5bSk\W5nꭔzb*%:.xQ43e%^"uͣ ظ8뻋+'* W@ Vgx yz6B?8BOZ';c&cy ?MM}fW8bWRv^֤ц4~&9A,`,Q9[1 tHyb1c<9I[~(/4%*otI ΰ.@n |Z@O2!O(g(41>$c-T?]T'q#1D:!:GhSq]ac).6;z=cҼKV;1CTjt&<غywsY9ֻ^pŬwR ~ybYe4L=3 {2f~psR$R Sq CT/=T7g2_2sΜdg3]f:o#a`ˋ}Nl1.*zQ7)I b斵N/^ۊW\ EW]1$uc-uT?u]TTqY-:O9疚aurր"F({j2߶3⻞X\,Kgfɋ1r$7#h-5~f:@L2 Fm)/ |ȅbhr\0y2:cl8I:[>~Bkoz= #w/wV\|U<e_bAo25l7&%"]6{2]gHcb2ʼnF=S B(D[sUanTCE fizr.>~aE dV~M/P(  z+A|)89&endstream endobj 985 0 obj << /Type /Page /Contents 986 0 R /Resources 984 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 987 0 obj << /D [985 0 R /XYZ 72 702 null] >> endobj 984 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 990 0 obj << /Length 1975 /Filter /FlateDecode >> stream xڽY[6~W>tc;vWj쥷m UUCN0H\vK}Ƿ }VH0NcC>di4OtO^N} %A4 Qrr)H`A˵AW_ 06Jc|$ H}stOC~+f dBJ%100yOW'h`DE" M_;;zqTH ư8 "PhکѾI(! ]:% B dRTR& QD&Alls,0 g4IeiW2%Їށ! qTf!gA* ($GOav1~>'> JE%ɿyz (d_g0ƊS T?+}TVUˎ/KAۼ+u 4/GGGCLġl7R s 8x"; {8cQOa#v1G~H`*wJzi-'=0Y,oZṋμ2`h:oPKBjӺ6S̖:QJ&]08e:ujoz>]SupwydBe?M: u\̫lܪ6Qq=t=9<JtLW?d}ح2P}[ӹLKcV2 [|-1INFmp?J̋ƶU7]=-?2C m-uAf A/roicle_v#mâmqkw_B̪4h| r4FX$l|75?|7~6_ɞwVNbcM4qw(:x?e wHpպ;ǣIuYY8|U7G>ݦwglF>{>;Ibn|x vTipu By2[*#(;ٹl!WM 1·eV} ˪)"xw5WD.;I;ҝ;y&;R+7^>뺃'҆lZ?B/u'7.~+"vPAob A\}HTn-4%_v~&ZHWyVmY M-FkYUV|llLkҏo&Bp#Y)귀R }*;5]}h?mݪLC:+}9Ns햡 #l: QFCN&Cc'.P QCj.k1sjkU饭B^鉕X&?Q8A :Q=1MOD]꣢T6ZE4+ͺQqg,] oOV&POfUZ=j]ʾ3 \xqIDXE7Ds GAe0GXUT~2⇭kE"T|-~ف.19,(5wAN(=%g֚hendstream endobj 989 0 obj << /Type /Page /Contents 990 0 R /Resources 988 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 991 0 obj << /D [989 0 R /XYZ 72 702 null] >> endobj 988 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 994 0 obj << /Length 1654 /Filter /FlateDecode >> stream xڽXs6~_#9+@u.7i=@l0!._] a0җNfbvWvWb?E܋(VnPO e^0=n" DSͼjz~C Ed"WD/5Jj5p=AV%V|(L3?g8, 2kbDPn}vuM5ی#JVDvv9c? CKϋ)!? 5rYdzZ^~ID1ŽBqքG\u-q5oà+AQ $7*)1 tH ~ye_|oy߷..2 QrQ}{!feU]U%Ԏ0k-fD )ȌG/iv)ȩd s.FI_*c?BxDc`1p=Jl(DD~8t!̹_v4~D$Gb."`xqڧ<R"$䳣|c|8$c |ֺ<$ D?Q^@B&QVڀV+ VZYh%\/"CpӼlаivbT'Ie&}Lճ}m6?d2$8Ec ըIF9T9LOK%1Qt0d1`X"mR3fP $Uūzc.C?6NnLUS@jqAVt}x'3~ob(͡*ЊvJ MѽE h46ɘj CHhrRW$e퀸 ;00[{ ]h6]mؔF6ivXGk;!ywۤ<1nͶ1!1(`ar;}y^^^ٵWPPwy/Kg)Z-g۟qw&);b`%[Yp1m RrMuZ7E.mx@`}rG^Nm0j_$axYnb%M?`M)Q\@-"nQ @*pn`Su-xkl;ZIYH偼̚=CLH{.7N5>y#tWRi+6w9¬ͭ193=|vk}뮖j6`26rZa[6O2xg$ԡYlv# +{i'I$#w΢=NR!g Hendstream endobj 993 0 obj << /Type /Page /Contents 994 0 R /Resources 992 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 995 0 obj << /D [993 0 R /XYZ 72 702 null] >> endobj 992 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 998 0 obj << /Length 2202 /Filter /FlateDecode >> stream x՚[o8)h5ëD.0 vI2>(Ԓ~=$E(]N0(P!rH1#SL Ϸ4_#pi^I]uv+(b5⒈9HaE7wV|\|t%㾑D\rejjٻVFJ%yWhX|)ʴ__E\1C~\EdQdu^!&8}g? #R9jDzK[`2?EB@CIXu%=JO歙n6)$t7tF՞B4X<,] |[o ([$$i 1 S RD@Fo7w5[Y-s+C!K+\71>Ҽ"O."8J ҙM v(a*z2nrTqL!ԫp|*ZjNq'KPW@NT b$`pϊ L0wd 6zpv#O0G%J8gg&;|0>_m >M/_t^"Ck Maa-fd #Q#kg&;p08_;3>mB `ӇS2_>j_|5Qv'%qvA3d T|Ucr=q!Z%DŽ7 jͦE[DC *z|3g6,&1heqaUA/^OWr< b$`hF"rpAP*,t.fz Ar< b.vf. v.]PNoJbH%wKҏfJE ̙M va`jUV9kJN0}8` J)%eWE('H  <Og63&y<l;)DɘnSu2L B5"l U{}£GQ;d=_QFB)I,hWqMh3mۢŞӜ(8 2QN:341 TÝWE#[ Jb2!'lRo taB*` _pmi$Vbu)^} 㡨o&y;0_f#HRښ_/@jzN4ѫo&;*0_ݵ:6Ms;cebR mZ_l;9|@.i-oaԚM1 AF=U%AeKKs HĜ&|:d_MW.5^/ /+BiʐAeʷ6rHJ+{s_AŢ!b~ʛ/!M?gOTauQ+|3ʦSL qk(& pw,M\oz›MӲ9]!wq9Z]‹+cB.;MVoK ͤ~BL$AIW^YŽ@r]UV2xߊcV7N˻]|i~qeSiCSIɷM>cBϜчz=A?n(QJTS1EqXb xεj@Y|=iy>f 'D~YTÎI)┻ &N럂qL̜O]SllST.ƀ" \M(?8@rendstream endobj 997 0 obj << /Type /Page /Contents 998 0 R /Resources 996 0 R /MediaBox [0 0 612 792] /Parent 979 0 R >> endobj 999 0 obj << /D [997 0 R /XYZ 72 702 null] >> endobj 996 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1002 0 obj << /Length 1988 /Filter /FlateDecode >> stream xYێ6}W$kF[h$MHEQ$y-V#Ko.XKJù3C$<c2}2f|W^Ͱ)#{( Pw%X~ ={9Qxj+Fb]|\y2]фSJ|'%f/V$Ai&󮥡K+4'(MA0^^b %c0^%!F' ϳy>(Ld4I;)f}C-pR_C#E)OU \&uBBs<!zbNbV+%oǪ7.>""N 1RKGN!Q ^*&(H)bC%8!󮾑A+4E$&I*cZ(xVMTJPRI~kHa}V2{} xz%\R {`Q1|`E{o;L|=Y8b͊dmU7k]=8`Ea,6OR_!Q~[F}-zNL^#0EI #n:V);gE{52aF|mR^jbS|VYnΚ:O+cC*] [[Nl [uس K'y/K19W IϊݤoU7}]m^ZW7 w/ e K$m/Rq%qbVx7LɓuϾ% Z&UVy[ʌJpКT[׈xP%Vp6i4 Tb7Sa%FVݩеJUY4FA1} @%Qe&3` ċ:jԳtKH:)>M> ^YuѵzP4(Ic_?bX4ز2dgm8.^]* 8jX9ܴT)T)Eg w>/VCyO8 l_Pp߼7_Phtmn&SGD2 m2u>~6*;=膙W,:*7HkH}EdR  i΃HRFAZeWZ0LRj7 Bo#=XpU9ugwz\q^D)}b';7lBŞцzo㰶PzbuYKT[)/e2 XfCz=qMGkKoy]8jz7vEd TU jϿoD^ ,6R(ClN37kJc lp =!/tZTV%0PrVX:an[ٺ#:Av +?VM5O>{{: |ѦhՑ> PXq6;is#-ˬ :HqT僉.<[*DBLn> FLi7Z஀u'vpB{7v6V#j[F(> )YB{tߐ`ZrdpJP4_=yee ڬy3&gڟ~#ɼv.21?z> endobj 1003 0 obj << /D [1001 0 R /XYZ 72 702 null] >> endobj 1000 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1007 0 obj << /Length 2217 /Filter /FlateDecode >> stream xZ]s}_яUæjgz:<nnbz{vs@4BTvRr 8ҹ#]]Iеtu{s͉D=#ܨ!K΃&؏z{O/ItǏxppm"OX]4IBD$tnAS{\0Vۭ$|sYbsn|'JϤ>>~׏`+"N_'L$b}\(n@VR}|ֿI8,Q$羐om,{T6z*Q?4 HKF_y9UͫqUJu?i[u%+w_6[bmDVhLhBb-Ვț-QYQ[A7nVe"T:6cP~Kk | ]zKyK9A؁ش&1upRkxfK66ܵuL=ᠭsљQgL<&HԊ€bYBuC;e?K$ [M5: kBdJ6G~i*J=$b=* POި۷p?_ QW8rȂ#!Z2jWC2[)p%F$Ȃy% KI [TE8(9a+i Qئ' X`۴)ID-j"ڵ3YC!S-8 fg98\g4ƉBC"FNA(NAx꫋CPb^DQEt"NX"r=+,a`-b ~J{ ;{Qʈ%9egee#D)ɹxӪ'̤-"4YɫHoE:(D=T}hg O:2EШ#),0(ppjdx53$#K\S[~˼|%-"䛰3Y}PdimS,C1A` DxWDVN˦q1"ZsBa wpY"0.y4lQ τ. Tu|>OA"~<,*2cVRDqLX튘N[kc߿]FrIy\m{23|@N ;OHΓ3/YIf2?*&KsQv& `vO!LKo [E8=am’Lz8ŚIDSxR 6[LMoҥi 4TѰEU\*V*&+yRok]ݲ( uy(K].DKz$6Y{Z3u"Z [[2qHs H5rMXj1cxK>oa,c>BƧ\$Tr 9ޕgP񸠇-u(5aݡF7f4z 7ء~5>SRQ1_C,.Sбo\ѰE眳8dm2=@~K"k.䫣۠ǫ/fC(56a^*=" ?Lg$#q=Y;5ߢ7\>%-f[n!Gqԯhlݘ )tjEշ /3 [ endstream endobj 1006 0 obj << /Type /Page /Contents 1007 0 R /Resources 1005 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R >> endobj 1008 0 obj << /D [1006 0 R /XYZ 72 702 null] >> endobj 1005 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1011 0 obj << /Length 1005 /Filter /FlateDecode >> stream xڍVMw(WhiU=䤓4i9]]`XL$pA NpU@.F@`T$Qjg 73h Gz f1F"_ߞ%Q,c2z8OtnLK4?s1,q@cN0F c;uLg pQFOz8jg(/ݦ>ẋ`* !IU#,(qc"-ȲY,$wȰ7 ھ!5;bWD1;H%}3#Y4NFp'a_7UZ,v$;5Ixz8u4m mCgRĎ,)bK4חw d+V/%m${S]#S[Al}Dv͞)/L]k9EMv;)HU=ku|z1L1XW>_׎jK:0(OLp*FRuztSɞW-.1.L<> endobj 1012 0 obj << /D [1010 0 R /XYZ 72 702 null] >> endobj 1009 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1015 0 obj << /Length 1868 /Filter /FlateDecode >> stream xYm6_6s&Diڬlsmgmi#ɛ7Yh)wX`Mяf 1b#ӔNSLO0zB7x\ rrI#.Xn;XxmD\r2 1ylHPrtm"0VŹLVI>{s],g2+̰6Ȯ uߧɻx~`TN?FTI5=N0q_bKJ86ˡJgS!+yHh2IEeQL6ܴ1X<+7ힳy("Oa/ݢ Q:5JiG+jv.( [̾$B.' rw٣[ l` !V 6[-[6֐ [=qZF792KQ*SW%[g큨ۘ_v!Zz5!Kir`emHᅵ8kmX>Z׬*͠";Y~:ڄ;2R<8Kn\tQ9p$$ͩg;] ܸW`SYaL!c ~+ Cm8`(Dl4D^B5"m(/w 1)H?8afs*g64tU+L9Z6E0ЇHჃ m lA }Q>:Z/| JR+xJP,f)J 0J2JOkV`[ڤO1^ qE8/t Ldy9:X;3TV\fۧK ҿ78Te0Qr4QOkVdٲ`.Ѻ~YT Jnwڀ!Fl!FzZ㌴ Ve!qJGZIj l=r(t`ւ\E}3[lYC,]˛XHmh;˝O7k'AB5me6۝ub%(M^ 4mB ,K)?Nendstream endobj 1014 0 obj << /Type /Page /Contents 1015 0 R /Resources 1013 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R >> endobj 1016 0 obj << /D [1014 0 R /XYZ 72 702 null] >> endobj 1013 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1019 0 obj << /Length 1991 /Filter /FlateDecode >> stream xݙ[۸+h+^%vѦtm.$:lGI_Û.6%iXȡp>r8?2t;/o, E$tC' a+{"#%YnƊW߮?m>|x_(F<t*?+mk& e[u9pB07Ź8z"kMZ՚x&R5[}^<~=vQ 02󂇱{ſ[=0}*a(Xv%ƈI.[15ڏ1Ibe_ߝA':F4ZEEc0s`8QxX; ##&(cleMU4:j^ !w`ۈT&s<{(%yx8YS;wVyf6e ڭՑ֩ C^6bFuA:|d ` w:٠']CW94U<ݞ2pKPL3SӢωS} ajHjp~,9&jWyTeq4iA=w fmr8 z)je~Ɋ]~ݏlcEjԣͲΚ b kӼ=^ܧi$/-C70V?1a c$U|Ilڸv?:m]gO1MiEC4#{z)4Iq(++'/0̬y/9'OW{e6 ;HvЕv׋m(kp8vb\&Ɇ} M6Ӱḟ,iUdP7|8VhKEj#Me]SJUvLIM[k!l }pUP'vkPc$BG]҈C!*칿xrj㮩nK)ʡcS7yDHJ_$Zo|k.VEO5+X߲8efwTs]}mI5ᇭZsg6 b!Zʠbɋ. ݊Voډy'OB/G}"ifANX8ޚcDIs5*߁++҂$0fMY#[E Ԃ;yAyq[r'٣:N " LQsbԦ v>y_Mqc!8.x6R38=dkC A؝.D ᘏr LpiLl[rXEOIڿ.oFra ;aȅ}x5c^4&*PlzSl,);~6}+Oʻ^"*'2cbX]&)UՋB4ijl2QD+衒^H}Ou6tu*+:C6#wr`}7awkg; ΤS,,);~}Q%߄1b)O0hM2u]x,)wYI]_w'sI>_ܪf>"9RțQb.ЄX }pendstream endobj 1018 0 obj << /Type /Page /Contents 1019 0 R /Resources 1017 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R >> endobj 1020 0 obj << /D [1018 0 R /XYZ 72 702 null] >> endobj 1017 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1023 0 obj << /Length 2112 /Filter /FlateDecode >> stream xřYo8Wۨ7MR$.0 fLf6}p ic]-J6X$pSTXHuH!Gy" ^3w(RIu/?oWW F }0Vq+ ""&@XDCK.o[??4Ř({{֛1e!^ +T:uH gށO?0"XV,ڇluc^.["u }w( ֝'Ji"P`+: 4[E**R0-F [@3&Z C)6 *(1[!BcX/R#Pqyjm_}:Q$H8h Ĩ;h`hbhh0"XL@i- ',rK7  I+j#X@( hiV+;sG ՉPC}jbu<5z5hJ;kzzP(b ³W;F`JN+"ͫlF҈!G9,5~@ b֊ْ>fVgb6Z.MhK|8f|R]m-꾜zdd#O[PZ{Ǟ2(FQTyzW8AyN<l+_봰U?5U?O3i$ZQI ޖzoJeCkrR{eZTSz_uqa9E,NF.NZ.=̋KF䳔GKP_ldUq 4DXDL~qՔ3P.c dNNy<]Lu{YZua;EiTI1.,kl\%jZW)u + U 6ձHWOd ny۬piqmע!6*hN~o`c%]9˲nDBD"تGFXILuuS,ˏ"kFf2U–eڙ3jNȷ+ȸB.Uկ7Gpwf! iUnMd1{GYx,r2{ŭG+tOM;͈ܔc\ԖR ؞QKe;=_/j6+wדD2Bה-<{l-Dr?DUƇϧQcN(R#t./$@&gx# gNpqJ-#訧#ra0*ҏ6]~]T2ɈaGi'ө4俉M{b}ѯ{(?:P샟$2X"Ҋ%d'2&2:$I8]x6[$(PfY)oU53l8IxȚxڀUT`dn,}v@%L2LgP`j'vԪ*Y8_\4E<?Zz#j N9X,i-:nϠ9ǾdݍɄps,qirY2sXusZE_Tϴډǖ9Ly1(K(Z( (&V(V&HqX.60n~S"$ '8/S\QLV/ccZzͷ "9^f820KY z&&Qx8~M>%zCt;Cx.;'I#|&2Xbيd99z2։g#:0G{LdoWgP ,%2Y2K{2n2CRݩ;L1MMH@9Y*sM2spV,%=U7UAn6"Jz (D]vza8</s5si)dpL&}m~\>Na|)Fpk0_w(tt٫;&e&Da|0wMY쐣=':sHNX,29î` 9_endstream endobj 1022 0 obj << /Type /Page /Contents 1023 0 R /Resources 1021 0 R /MediaBox [0 0 612 792] /Parent 1004 0 R >> endobj 1024 0 obj << /D [1022 0 R /XYZ 72 702 null] >> endobj 1021 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1027 0 obj << /Length 1857 /Filter /FlateDecode >> stream xڽY[o6~5CRD耮v]0}jK$'~o$r"@DQ!i`#AL``=F~C8b|Ct [7GDLb5_g뗄#% fK"fw'Wgo_  &ABFHFRmM}'tjOU1&(UY}5 J"ɸPͪo g܁MoGq^0R`;bp/tG#||.ϓ"t@?$b ˣYBɢ)o?Q> "hЖwЁ; vhg`*Q/HUbͧ Ls$$ `RxDVi&}"2=yVأ͕^=21/"[\q2N-7COLPD"L@8磭D8`*SuQ:VmȡiL7 Y5twmzDb]E;-Cn?17pPt`]bb-㞧;vqÞ>8o'g⫶ڶ4*C-|1'al䋇,am%WbҥW2/U{6{ {H[Ǵ 7/}$G .{ȍiE1ȳ1麭 _5.7fީŶL'DU=Cz + .FBEzak`vةVojg)y>Z!B"#C hs֊}dv%q_\AxT\~Wz%P[]=_:Ξ3`phሐA20tOYc_DF>X,+cG -$I 9Q0w+e?a_0Vendstream endobj 1026 0 obj << /Type /Page /Contents 1027 0 R /Resources 1025 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R >> endobj 1028 0 obj << /D [1026 0 R /XYZ 72 702 null] >> endobj 1025 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1032 0 obj << /Length 1602 /Filter /FlateDecode >> stream xX[o6~`c#RDh6m%viش-DGy͖lZ.0 "xn9%f(j͛()P D? tty#{ӅbvA QF9Ȕ1z9ݩa 3d߂ î*J9Yҷ2k'~(E=x\ash #ρ7ތy0 {ňN藝Bmp$_!AQ2q߻{e(4v0'Cxf;RhA sHBX_+0Vả084Y)O䞴@̍%#9&F;%$k" #GM[o`P Z,#E(B4uuv!{ꎴjߨ#C|)bO9A*Iң+Qg,U!'t| i('[ADZ;-b@2e@.O9"C/] Y R?3t ))&>L"[ݾ+] a{u\B?W)c Գtq"D`` ;Đ=GZlt'(IBGoZzJc8>J0ĊeeHផ#nVZ¶O/peQ%ۑektp ؈r)Lw\NF^ARߧWA =Q0đhHឣ#nZN+r)\EUOD#[E7U_؃0ʋqH>C-M:mQjgTAPCU-+ pB[1 [1fܿ{mR?J;عT;JGZTit*> endobj 1033 0 obj << /D [1031 0 R /XYZ 72 702 null] >> endobj 1030 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1036 0 obj << /Length 1288 /Filter /FlateDecode >> stream xڝW[o6~ cCRDh.m%^wIز-T=Ik`?~"Hr`;sCa/^7/&[ ;cGL=B Qi69 #I,7[)1[\/7!bIg1y3d$חtr@a_c"j[5 i5%~s+=jm"aں  F\#* 䓫ɯЇ=E1ekCI%0/>FH(ZySFF{JCxS(rh}d@(&(U@c~`H%P(Yu0WJV2D t,ј:Mu~l|'u kC&ZGp@l9Oh^XJlni#c9ʤ .Gh\LlO3dOߡ~?9LIȫuV2p] ĬkƔ Yu֖=`чEFߠC3Xq"* qࠏn C g-r90+6yZecE$U]Lʅ]UlS 282 IKʌtVUj5v5q򕪲f]id>j9&\mgry,ZcFE9׼hIa@>ipF *LA!`183OԌ30chZ.v}pʦRtNʕu/BD4l5vi>t̡}I$O,,˛){O!нN7zH٫WΞSѨTt> endobj 1037 0 obj << /D [1035 0 R /XYZ 72 702 null] >> endobj 1038 0 obj << /D [1035 0 R /XYZ 111.7576 669.4409 null] >> endobj 1034 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F55 489 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1041 0 obj << /Length 1438 /Filter /FlateDecode >> stream xڵXYs6~ׯS$d&uIݤ:=<dqC%)+]Ha.L< ?ċc `1#=Bft@"qԁM^\ě---nW//.B%%LMxwM s:9hAacI<"mA0*T5%9K=2:05or{ #.#*%$L s`L%qH ưثKMP(Xu0%P'$;b؂F,1M\QS_͛JfT7kl8 Ixal΀F]_4wvZJ,A>1ʘp+dM! Чm8 >Z:_rJqgWsԘŕֻB8RI6UeaP//88c>#ZpGP?$VZ2N?diTC\.kUɦd6+v> A A R{9jQydI.Ȭ.RKUUjag[Q=0KwvDQKoF x9 h_w$d ( 9kK~?m̽?/*3{|%'^UKsĈ$p- x:n^YB6b+c6 FWe]/;';]|j=ު53޼n2ZYden>5XOt{b˽yr[ËF˲rZߵl 5X}[:hGN _~t!ZBZee6(>lx^MksNGr%2PKrY3¨٭prUmYU^6teW0VF3>{]3p⽗-#p=ƥ * uxS1vM֘kjqY8zO՟n+h9$> endobj 1042 0 obj << /D [1040 0 R /XYZ 72 702 null] >> endobj 1039 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1045 0 obj << /Length 1273 /Filter /FlateDecode >> stream xڵWnF}WPsWr7@ N$iVNhTe}goIъ_ C.̜! 0 Ai(&8x7&ĭ#qiP/j0.a=`"jqvzm.H".q_{5R")t5 M=ƺ8Wqߪ?ˬL黴L&0'JALqLOn` 6}`$T,-L0JHI>c̆#!.BF`u"X qw!L竬"O7̊uiٺy?Tu֮ ;QgJ`$ 30,1Jr+a|Q-SFY{3*[ .C:`a h]?G^}޴fS8K Me׾UUn%^Mq+kP$Κy&njɓLߗ_sQ8>Y=߮>:MmdtݮNl{ڟ<~]<Ҷ/JwSޝݛ@Kl/ږYp~&}US]}uBqj8Y+%ΜM:ƽچUӜ /w.&{(>Nd u,˫]qnƍ(jwkܮfUmrm[յ7:ϧWP^$S X6ٍf|Ik䮭ҙ./tHgqi c,'Vw5S^Ba_‘c:L+<ń;q msxNoCSV *,& Q17Ș(W"xaRV)$4;RA#Z{D1|Mj*ff&25&Mx3®ue_ 쪠38Wx`l1 {YSQ,lN~~Dz?tAtH~xmItPa=`A_Y(`ia_8) G!M)8yWv\a?t)W>ʮx)эTs^&!B;qh㈖9}YE4}P;H5fJWlz>[Cc13Y$1ri6Eq E s|8uzD2G/ώUw+#A!u +0̤_L@bh ]/^.5\c?.W3r"))gTM7Z=,vq_1$2A4L:abK3sendstream endobj 1044 0 obj << /Type /Page /Contents 1045 0 R /Resources 1043 0 R /MediaBox [0 0 612 792] /Parent 1029 0 R >> endobj 1046 0 obj << /D [1044 0 R /XYZ 72 702 null] >> endobj 1043 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1049 0 obj << /Length 1246 /Filter /FlateDecode >> stream xڵWn6}W詐шM6mim<6K}G$%Kry) Xxxf8$猈G:!2`|;pCknqPx!ZHbIX}?}=b  .F\Ԉ/֌HR8]KCtc]SK鶜zLpJU>%n}fu:DTvV F FT $Of[3'-^mW"K@X@;$KO}.L{U;K;aj4.&}=a\eR>×YZYl]nQoUPyNO"!"}fUG%Zw+d}O-{#,yVhegdv,z4_lԪ7v?i>nO1GU٨Մ]"*fS}MgeܮMG Ƃf_zv{˜"pY٣:#f1z*URHz+X2c>&ُ1_o.x\ ZDݲcc{W> endobj 1050 0 obj << /D [1048 0 R /XYZ 72 702 null] >> endobj 1047 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1053 0 obj << /Length 1242 /Filter /FlateDecode >> stream xWr6}WCMC7@fԩ3I&I[[RY..Hӷgw0S/[3Û3`#qa^TaF\A=䜄HbIŝՕj~xrx$\FjތHFRx}Kctc}SKxE&V?9K=ͮn0 e,-L0RH/Htlv9mc?S!p>p0‹ IbYY4U̓:)淪_X<#"`E@ fi`U% DnzOzepIdVwm6mSh4ˍR2BgiuO,{<~\4ERݫfF a)]]I.M)EZܟ\6IqWV.IU8aViKp6ZYJu iޕYVn۩_Led;K:/:>Ld -F.Mjvܮs.YۖUչq[KyĜP;cmCݒ~:g^ meխ.{oف.`ao/1EɄsm~Vx9b!&='|qᏬc'=_PrA57m1RW No %7z@ʜa$0> endobj 1054 0 obj << /D [1052 0 R /XYZ 72 702 null] >> endobj 1051 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1058 0 obj << /Length 1419 /Filter /FlateDecode >> stream xXK6WTx/I!l7hڠi=I\k %Wu}")K2כ )}f8//0#QF hh oΈ#pʅRxQDx "pڃZnH$$Z8R}ק+^clWRXCbŌ"8SM+01f<Q .rQiօպ3V/SSFZHL%bgAP-!PEv*ydT]bQ3$?S$C )QьVFkSjټ`APouwg] nƩg^vfg6v)|͔{C~a3[æPW< 4L'>)sKA_Pn3$,tDdBlg59o7M,=')wMKC n=_OL={><ϴSևH[S92fAż5*@U67+Is%qKmQ6gX\po.)0P]Œ͵euӶZNCn x=?c"G!?7tVa J+hF8%8J;WsTG _9AL3}IC|ůaY$K3&YH"1`Sފ3endstream endobj 1057 0 obj << /Type /Page /Contents 1058 0 R /Resources 1056 0 R /MediaBox [0 0 612 792] /Parent 1055 0 R >> endobj 1059 0 obj << /D [1057 0 R /XYZ 72 702 null] >> endobj 1056 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1062 0 obj << /Length 1469 /Filter /FlateDecode >> stream xXK6WV"EJҼҍ"Ku~}")K6mТ- Dҟf" %A`EF^Ͱ' ((Z#4JK! ,׆"ه四18 ?irD`tN1IHQu> m4N0YJ CIMWҁY|J?niY"=MXkn`{ $]AVć_1HEb^;pk0wNX p.rT6݋m rӟu.ODiR1=pOE.`WEDxc֦/|GWD6Zi>`PDS}א15d!WYSƾ򟹅|Suאr1dU R$D2|;e30)|O8Ӻa*AVBqì0[~Ax.(D, =ei2-8oXøXkhO„> endobj 1063 0 obj << /D [1061 0 R /XYZ 72 702 null] >> endobj 1060 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1066 0 obj << /Length 1476 /Filter /FlateDecode >> stream xXK6Wh1/It4It㢇$DBp$w(R$vZ4@>pfLa#^HS/gʫo0P Fn "!z/K{#%Vk"VɇOOw/K?k~ի@ oijP"[g6%|JZys2/DǴ'%`F g<$1/\.kwh?bVr Dc:uv,MY!xtnvVVxnNiTݔycow6%j莍+.7 z\\^VT6UTltC˪^sܥqeG'H2ȏ`Wi~U0&}lLًWUiݤ3TU2e:; zGP6P-̓bL# #2=B!n*^|b埦& r61dZRlZ}D8n2*>ô)S$C )@!%!=Ҋ uΏd> dڢc#&>YF3C냖pK},8!3+Kib~8O, L:(4$Lpvk OԟiuS?Ԋ/NuI: Ɠvu#֧ aYgBF;׈ǨnG|wmjWi?[!l;v`\2fIhJMy7VG>~ p&{sub4à4$tYagK}y yendstream endobj 1065 0 obj << /Type /Page /Contents 1066 0 R /Resources 1064 0 R /MediaBox [0 0 612 792] /Parent 1055 0 R >> endobj 1067 0 obj << /D [1065 0 R /XYZ 72 702 null] >> endobj 1064 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1070 0 obj << /Length 1668 /Filter /FlateDecode >> stream xY]o6}У ?%@d[񰇦$Bl9ٯߥ(ɔD֭=5 0 AiNpp߼ 8A7G 5HaEek]D\r6 ̗ HEJ.SY ØKŹ^t$L$LOi]11-gwe:Q%UH֝bkc>(_ <1}(Rs%JfF{I I1$kGXmѕB4͚kQd{YnLB))hVS*ûQ"D8b++2 !V;"" um fS Kcan0Hy$"ʩ4𶐡ݎL;i#x=sC΍IUpc*԰*UUpY*\b8fxTX$a!5cG!z~!\VT:1!$#%KjV:3̇ D6}iMaAā9)qc԰qY8VtaE 7ե0GAQ,Y9ߔz%2 |%ze&EUN5FxԫeE2f}E0fk3^VtÒIG + b(E/ˊ̙'ѫ7f6|6ɌoȎ^N|?.+zF&bp/B (5ɶܙj H g[Cxb $%_J8vݮ i Sjk#7Se-֋{+ Bj?<ŭWo߭EV< K:cP:1q(ՐdM#~P!'V?\Har]uZ Nb%\1BK(]u+~W3C^$iVz\Uu6^1rf+TNuNk:a8i'@ey/h|q>2\.tUS*n'R) 5:ClԚ__}Cu=&QT7qIu#nB0䉌N4pNzwTWe#),Isغ65X e?uy[HˣÄv, (;!#?TnsT*Sa+\UWПRjk{.E5z#VkKx.'8/#endstream endobj 1069 0 obj << /Type /Page /Contents 1070 0 R /Resources 1068 0 R /MediaBox [0 0 612 792] /Parent 1055 0 R >> endobj 1071 0 obj << /D [1069 0 R /XYZ 72 702 null] >> endobj 1068 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F55 489 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1074 0 obj << /Length 1784 /Filter /FlateDecode >> stream xYKs6WViB ;ӺIΣNILSKRv_@P|dΩ ?[`K%?t)0] W^/H}/! Bf=6 b#p؀-^"|I0RXjOWk$b)?kQ#%R˶mU)Jѵ,֛@85YE0'\˾A'5t+!0* ?9y璾 (L4acX%f%  L{IHImy!Y)D]nUi}VI`Cw0^ 1IjUA`N O#VZZYE46b*NAJGQY_Yqgc핇H?q}#IExZ9lЦ6Z[+:xw䠧/naފ۵fh;C&PCR *cAċ% xRLQ`O)) ~E4~@a|79'6zhExhwSp4Sة _~`-p6`*6)  Tipr<| ̄Ӻ!821^fۀ88l0C[+T(C}hΕ 49<,j@V社͗U&46Ҳb:ή,>gR)E_4}6IaH붺Aho>ހQT6gMyX(.= z- 4S^W0{]$^Mu$9WbkLQCgJzܵ /7T^bַs6@kwczEv…M5G==W} *#9=-ʴ fFeo?psh 0I v8u B߈Nn)w衻tC|m'7E~#wvבYC:n1k7l_%yvfq r֮cY,l0Li\WQV+`jAh +*E\-8/c1K&OQq ; xVWƅqzO}^@mtPads.+K'^?V=I!(̓ΡqQ-WQ}9Їq=@ү#Jq;1E$F%%Bwhm/ZvӾ*R":|yk]Cz4,)Ljs*geKmyr{hE5VwuJ"~Ds}η^7xC)@Ͼ 8g){"41lxۖ7݁V)h0z{]LGStgs58}eW艪T=U?Q]9YC(gу/dxZo, #x9pH7 ؗ(iئ5,~.2m1req$8uYDx{1N4̽# > endobj 1075 0 obj << /D [1073 0 R /XYZ 72 702 null] >> endobj 1072 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1078 0 obj << /Length 1315 /Filter /FlateDecode >> stream xXKo6WVX3|I"-uA7H:.zHrPl:V\Iw}/E8zrßf!?41 0s5"p#.o(R#LoibtHbIzq~q m@\p 65].7B I=Czq<]q.(nTmz2eV2N`LƅV̚☚3 b:(0J!|#ngc`>ZRȱ^mVv2+9tH"α4 )֓iHqde?:jUVvnmK$Ta,+jeGO?l!)a(?.mg% X#<`@VLUfpoŽi,KU*>۩2}ԃAej]^wBNccUesdYQ|%*[[&/V|)CۛچbL@a$] > B/~YBxQN9/ȂtƢ0PwaQQ:Jp?(ɐ -kG4*0O:>|)bt6_,vJȍ丹T{1"`gZ6 Ai`zMMrkp9ȕqR;ɋ #v]l~ٱ,kS\8Nw0ЇM6r3dJu2&٦8l/nTrSj5,M60UrF $Vus25d+%?:2 O 'vFնߨUn'y !&cd_,FГ"t ZPr ?qxD}Ax!5bfV@4p=vm} 1zAIskT8QAW{(W:8Tl=~7>ӳvN Aǫ-#.sEiF2_;lvN 4dO7TVWmi?Sk?pjqyÁjf0ppDx%0lr=RK؟3z;9A> endobj 1079 0 obj << /D [1077 0 R /XYZ 72 702 null] >> endobj 1076 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1083 0 obj << /Length 1469 /Filter /FlateDecode >> stream xXK6W(1H<@Ǣ .z栵P[&LYIEHp(` Aipp+3RCX0i! F rv`"rcԈCū d djį1{lHP2p5h@}{UŘVg|I^yZI 2>054k #b| FTIgLf]l>ED`cB!ưEh?r^GQx=.sW n(WvR.,hA" d,dNrH'$A fPRDS؀Ga h[_I"7~061jϾNc$$yOARdr|UxF/HQ|>o@B3zgF8q$i8qF33(j6E+o.{ 7͑1T>3'&J/^S2 ^b0GX%UQs@qpz/\w`0$TfSvɡ,OY kX;bikp,V ϻ!Gg0eq-psWz0l5O˲^!|^yt45z<yc Q>(y IՊ8X'X}H{D(6[~t ǾVohEmNOzU~TQj|H"lZDKJ8|nKk'"a<f&YSxbϊe^V"D;Ҷs!RX2tuUh`d)<'Պl!~8b5I(uR1Jϋ*3M54H$8݆f'rIH#3\8)p$Y¦•7=Fmd~E/YC7UZ5{t:]}*JEt5-l1Ӽ:tzoՀzyk=4!CY:%uװԇ@"5".߉onE|o/B[TMl6\y[[h;Zz9m ҇tK# l1'zZ$Z,yh*'9ֆ;s ʦ!7.'+;[<;ᮏ໦̀%&e߼JS*Rk&]& Y d8CUW"aC|;⎫7>.hv[_R]-<>}%#78Ѱg%Snp/uc-endstream endobj 1082 0 obj << /Type /Page /Contents 1083 0 R /Resources 1081 0 R /MediaBox [0 0 612 792] /Parent 1080 0 R >> endobj 1084 0 obj << /D [1082 0 R /XYZ 72 702 null] >> endobj 1081 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F55 489 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1087 0 obj << /Length 1470 /Filter /FlateDecode >> stream xڝXKo7W,|&ס46Hj!ɁޥECA;|J0 w?|3D $Hh`OvA0cw(D([uc}!Q@0pFV[1MiMNA)b)@D*7g&MQgipjiNymA|cd꟦V0e[шnEdJR>0Upz(ʒ4 hfA`qjaӣ_ >uHQu@?3ΎIdSf,Lz<) QJR;3hAVe&4Z} !e?>BT2=֕(-{!E|u h8QĢ(%a< s ^hʜG!:ђF|BǛñ~Q8+-eU0[xeTy2룉8OC6/ȫr0vQezu]ivǶ1? LӂYS4A8K2h} =2>W-~W$"-Ř"O( YSW)9tS>tY9Bn,egkКf(!b(F `/~n5* iC OU/slV4[t u6oTj*=WЄMp }j)e΅'CXMnb 욎2F/V# 8wάĪkw|S/V >p-ACʗv+^BRx_}a 5T;E?Lٕ䒉]{( f?Zbv6ҎޞG/+6|mk3xh/Ӯ{o;ax]uWCYvMKގ@qm3f}1W62k 68F }[c//LbqyuMa}^9yo=B\70 uk't+@CRg< l64mPR8Gaɧî-z3`|ߕЉa쬗WXŘqK)wMCEqz?<ط* Gڃ$Jm2^9z1}N<%>Z|yU^ +F~k6EܯE`YM/c;=Da޲;QƏy@N=F_+lP;krFztg ƅgBh"B2 0 5Zx8&_" |:v(գ+_VЇO(81пdۗQ;J$vs/I|ÈHXj`EXF w1Qtendstream endobj 1086 0 obj << /Type /Page /Contents 1087 0 R /Resources 1085 0 R /MediaBox [0 0 612 792] /Parent 1080 0 R >> endobj 1088 0 obj << /D [1086 0 R /XYZ 72 702 null] >> endobj 1085 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F55 489 0 R /F51 451 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1091 0 obj << /Length 1674 /Filter /FlateDecode >> stream xڵXQo6~0$CRD>l@&Euwyh@r,T\IN#)ʒLݰ"sN##S di4LF^MHO`RZ`q)>\ސpJ0X|ePZMJ1T)Hiio >cy1 LD|=ez#5 Nlgv+K*凵P3WNL=Q f{}ltP{GxnxJk\|  G?jC4}56 aDB<;Ҁ Bs'N\]];2+͓)TVʷP%J!};8Dpg䆃Xe}CҩY{N7JVc7rS޹eu!;ϑVG{ooɼnUz.h~/U*&ۤftz_m|S3L۠(Gt{3t> endobj 1092 0 obj << /D [1090 0 R /XYZ 72 702 null] >> endobj 1089 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1095 0 obj << /Length 1729 /Filter /FlateDecode >> stream xڽYݏ8_c"5m ؕjzi Z9 /Đ=&v730,0#^DSo`~y7! ! RJIn*? x#b$f?^/|q&@]JL.ΑH}VoC1&@G]i=M%yR4=rY R>0Ug'`Ӈ Fw FTp&,vMn'7zu˥am< : {a(cX(Gb6h0L/V8ϓһ47WYכ2%UM`М(`jt7DKz[6]m1:"kKqawtnW/q#F Δá,Ξ~_11bqZ^?]J篾Jܧ|Z Oq-8_ˏzqsug78$}:OkŖdE\ü ԆQ۰ah'L:4$9gT M*iHfsýa{lR-eS[/qvFcub jNw©*ݤXkn*ya@ #h;mr ~ջgV?(@)tT+|UeRU֨~vh6{Q׶SOspEm8{뤫Ԥݞn@жE6+$ei7H_cϴwbnWS[ ^¤SY~$gQKS-ꍄt.!W|ߟo0){^T Ts ) < Ost^#6%o'zm}gVȁ9]0:v(׋4 hS%0ԋ-4$3TJRVnȳg Q`Y,GlIkf^e3i葋hzx0qdGl_V"_c'P|QQUsc\d;h UTJaK4'AԇS6b <t&3e,?Aw5a Pt7Ռ`:ful9)HsIictlCjARt֓| J CP]Q"h|Q%FQ\uPQ(\) 3/|ӥ#iRNTQȱbyAIC>kWq"D)̋%&a n]3n"|)5bo8Pk*2 eU;VPy6=%aX_zi x5>. |+u>ՆDUj~дsf&Umq>oA6vQi1SP݁l׫³t@J"U[W#&xη ;&nLa[mbCBF``̐-fu#F.vuxX}tCFP(Ȉ~"vd}hAK)f@PXW` endstream endobj 1094 0 obj << /Type /Page /Contents 1095 0 R /Resources 1093 0 R /MediaBox [0 0 612 792] /Parent 1080 0 R >> endobj 1096 0 obj << /D [1094 0 R /XYZ 72 702 null] >> endobj 1093 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F55 489 0 R /F31 314 0 R /F51 451 0 R /F20 313 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1099 0 obj << /Length 1338 /Filter /FlateDecode >> stream xXn6}WQj;Z`.4I[I ;%YJPpp̡((AY)Oh$UgD፽F' hJ_g #R ɣ]aU#C}:_jVC&"5CFx8B azTlWx?&d?x ([AYFw4ZbLFHM7^P¬f$).֣ϣK?A6!$)[X F%BPaZ]@JJb,v(y3B|\ahPh]-(hOCfC**\ h3`ˉâ`aFWifK<' deLc,P'+vsϾ7m.""i`C3&)E]~{u5oA1ʉK[=FnCf4DTCfCWuF!kdaL*W{* )q Sw$k+fZi$Jw~,1"h~@JY!YP xbfJ۾ @BW\c *].,#+;giuY.|w~H4$% DM\tL ‹WnŸOaֳ㴔buZUj1 /Eղgn"`fCT]A-԰pPOUE]3 >r EQ>.W1Kal[Aͨ/ ݭjXTW z^ L{5*)8`7,s`2_Bw_C =lJKC32y7)l VItG/z߲ccKSg8|,-*o<)o4 ;Sa6S_O-`Pҟuvj?{ bUkyC$y}}\'jYTtT1裩0DS 5LSHɏCAΘ.sͭ8cW x"&Z$q*;,}U›jww]\磛U!zf]wA(͆꯻ZͷzKLϻcvu~O>]/s"uRyj~DdD < z:EvϣE,Sz.aU^P13gx2*ZQV!u޺ M\emr3K7o|W\endstream endobj 1098 0 obj << /Type /Page /Contents 1099 0 R /Resources 1097 0 R /MediaBox [0 0 612 792] /Parent 1080 0 R >> endobj 1100 0 obj << /D [1098 0 R /XYZ 72 702 null] >> endobj 1097 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1103 0 obj << /Length 1624 /Filter /FlateDecode >> stream xY]o6}У ,/D>lڥ(Iī-.~$S%%E[`(=9$A$,9hrg^̠BA_# Om;:=-12 ~=y2J 5.=J0uis. MsڈldhM2: l<`N+T%b"˳k rs"(s}}D %Ҥ:?(aFd7J7??hJRf*3[R UByf/?.Ԧb Ja1I*P*dkܔUGePD4 d`*=?z6UZQP0AM$c{qCTYXH:熇̗̯|ˬr(mʒՂ=.1ӓ^#k DngVtQwײ,/),)ů)/FrԳ İsC1Pa208nmģ;o5bHaB6lJ0߰}h?ėEBBJ uk-h./_V;:0Keyg3`o=lPfX `L&lR1=Ը!*qX172/)#L=>Q0?D|TaS.jD:7Z7A#%=:XN? u9PvӁ0I4SexKd%F9q*ttppA46l6|õG*Q?+[ p5> endobj 1104 0 obj << /D [1102 0 R /XYZ 72 702 null] >> endobj 1101 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1108 0 obj << /Length 2360 /Filter /FlateDecode >> stream xZs~_Gi&?ҙqrwgZǙ$sڢ-,ѕhܿA"H&mx%>߷]HlA-4_h3+ߝ]B0Qpu٭a5[&K-[\yz~o3"0&Z -.[cU,b)p>YC a~ڗj[g wbDPg?iY@n]΄2p_q @ꕤ:||eDj;Jz,p/IJx^q,>kP]k-rJʍܼ'Ae0p5,,1wg`޴kPhKSTe=Y_ |mF 3KudXyk ߼W8[[AW NJO3"5PDKRKeE[u@NŹ~J|t:fW,ɢ99Z1Cs9md9$#v޹}-?z:VMxA[_-`-o-:~z{}V[Q, 3 ΤYVbsѬG}YIxC±e!DZUd0EV0ek k+F"Qn9a"0ya#0C>LfyxyQ;^wPa"h"S $#NLK1؁ƈ!JLfQc. Fvd"s8 Npp rh:wq @OH7<@A|`lI!j*9El2| k/;aBrU֌r(-1w\*>ᶇrW}s7'`ul[6ng]ٚUS~.vZH0Ӎ,hϧi#Hw>O9f?nuGGwI5uF^Y+ m\&2yK (dѠ5I<޸Jjږ}k[Boq0ctZ2q(N&rZ*o4K9KS0)ojқ{Uv~OjLq 8> pv jeE5<ѵrYOkȅPPl+XDKy->L8L;A} &eKC"K2T(9VBjb:Z9uL&CuHݾWWo\e“V`'В'>u;\`AjJ.N.6}ͤ:4"g 6ns7fyTMҴC-Ni6n̗fCi9퓍~ s)RbҔc`JLlVLSi1Ũb-APYZFF2b厣҄lZC{ 6$Gt)%CޯPFfOe%oxeIJHd =%o4+qN:'xitxl|0.e9RƆ] ]s:@LLKFh/lv)i;sa=ʖ;knKkaKJYcA&`J lVS"iMĨ*޸ZmY^RP*=I6SM;VuΜ4Ǐ=|@Pjro)Of#Q6wҪg]9E/|q UVݢloFuld`Bٜ'[ QwI6Y CҒe0߽Q&p*pb_+3tgphEO7S4VLuܜB d!1ө\p1Nw|t߯BE1dƢxT_aQJAO18lL+&c)}YLv % 8 "%?Vczc$C1tm,*ᗨ$Fvx<~3 l(9Nfd0Ef0%s #s&3F_drF dFSdY2;2i2cT.~H,5)(Cqu%hc>n[|> endobj 1109 0 obj << /D [1107 0 R /XYZ 72 702 null] >> endobj 1106 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 1112 0 obj << /Length 791 /Filter /FlateDecode >> stream xڽVn0+xpfiRPWEI ߡ6K,EQ'R@N d ye #2-m9G56Qp1 S.@`1$y(Y*D2 GwB6RiÜ#󤡱:,i3נzhSIhMy2[e~AŞJƋnbMK^q(w֑e GSN cRXz_kGdn]tR& ߓԂ夝v.+f/sIDoOqf!і&L[-Z]sk9?~e:FsUL" & >5Y9LVj' eݦUj_2[}pS_ҍ_bI VP5U~s 9`5+w8`wE摀 fm/Ww7"Wf8?fFV*F_02aȖʟʢ'CT%NCy Q#$>*G;lQZ!jIw2fś;MW"I%* 9RPK9pzC԰ 8`JN~_U]0sG m7L0{ 27_ʋK\wL}0Z9Š{KFA'0 0S7̪+TrY%g endstream endobj 1111 0 obj << /Type /Page /Contents 1112 0 R /Resources 1110 0 R /MediaBox [0 0 612 792] /Parent 1105 0 R >> endobj 1113 0 obj << /D [1111 0 R /XYZ 72 702 null] >> endobj 1110 0 obj << /Font << /F15 309 0 R /F34 321 0 R /F33 327 0 R /F31 314 0 R /F51 451 0 R /F35 330 0 R >> /ProcSet [ /PDF /Text ] >> endobj 951 0 obj << /Length1 771 /Length2 1151 /Length3 532 /Length 1719 /Filter /FlateDecode >> stream xRkTSWqYRyi y@H 2@*/ !䞄ɽx0!(5*PR-#UQXR&`]]CNu=η}>8ADcR+ BB `h$ ŏ<)c<)d2E,@dLr&I2S$!yIؠP*wDL(D*D\It:@P$B!S0Xa$%C+)lr`0H( QCq4hGؚ)"SI" \"H`31) )O9P ݕG% "ᨔ<NCf:17 ׫nPL)O{VB"PXOsa}m1l5'' R &((PfpLup0$8AWD2*z{/.Sр iEcx_D~ A@L:| }!SeOv| wTf.Q5gľWuE^C?yY&GBVjq˃#k"}r=GyId`yi1w((.~VGI{HcSrwKmS:HPr68Ftpmym\ˏ~ђ[umҙy) }em^]EˈpcV?aͶ_h3Gf:gO9b^xMv@צ֤iYS1[(M~>ePzq4UY&ŰeT_|Swtď*޾9\oN9Qu@XgfQimy3/]mH+D.8#^nYGAؙfZ!0U^Z?Z:ȩ:(w|%mĖWjV.qA$~Nۯ|˸GE3+T\ۺAaH2R]Q&N]y3-|aI }/z֎ ƕxí>Cy{1dcy)h{ܱ5cC;Q]۝`TY1)slmd5*ymR;$^t﹫nŎ'UA`Ρ@!zzftmōy2u1fM٦kΎܫe;;ٍRȚFsŕ\]իL0ѭ^j3WL>u(ںAe,iirn4=.ԧn|öcCz:Io|MNލj7S#=[)uIen#oꜞg+O#nZ?hiLϒ`&>P};-z p.9?ZmT|ѥ^D?/Vl;q6rM@(> endobj 950 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /CRRSOY+CMMI12 /ItalicAngle -14.04 /StemV 65 /XHeight 431 /FontBBox [-30 -250 1026 750] /Flags 4 /CharSet (/less/greater) /FontFile 951 0 R >> endobj 1115 0 obj [762 0 762 ] endobj 1114 0 obj << /Type /Encoding /Differences [ 0 /.notdef 60/less 61/.notdef 62/greater 63/.notdef] >> endobj 488 0 obj << /Length1 2241 /Length2 14802 /Length3 532 /Length 16018 /Filter /FlateDecode >> stream xUX\ݲI@ܡqwwwNpwCpwwJ/Ϲ:.Q]Ϊ1lHhl 6֎t!eeF# )=PZX ``X _@![7{3SG?Il+5@Fhao P14:,-t;Ff5?N6 9ϒ3$&%$idcm0#ڀ> rCuշ:[Yw# ccߩ9YU G}K3CkK Bff@#y3GCS_avu_Jr=-Y;*?b? j+@_FP"^i61260@D,Ft Y8 `lcDeK} sqX l,-@{C;^ uQ__@֖@㿢_LpZ:9 mDXn@?!1 K}?Еm@ac 7]MemtklWH43H+hh Ho7qS? aKßfvN 26fegx@?A'V9 ! !ȿ $(@vbd&@N$#@.R"@.2"@.r&v(!(!|C ?rQC ?rQ7q\4^ @o 6`wO 5'``hcg3i?7 M -B_j_1 A2 AN!H/Y9A,_ AV?{/Y܍!/Y9 +d@V!/Y=3̗?ˏsoF?m\=hhY@#h3xG=v66=@W!҂!WyJSpHT4Isl}lbbeѨzSy:>> CxO ?}gt_f=e;]Axk(ԣeeTqli` c&)[%6P3,'J1K^ ߰eQoK:Um-vs|VKe+"EpF^7jj ;wlS(F뱣Ot^#w]^ɮO(y:Gy z҆qw/mHDDfL7_E2$syFy_>jdh UAY4hoQlyw/YvҡiyF^gup:vnqme54zC,Tfezբ?u*/sGX\iX0|j-q 8i'o2␨T{󖲕,J$ 0X=~?>6?rRVd){LnҾm3Wp؎J@ yw-My(Tq;b/CdraP;ŻO`ky7=.!ַOt|~RoҺ3BosiCؼr;ȡl+0ӱ T&="ɬrd"}_8Q0$ւb4M6xeђ *Qx,5XKГRa>V}8Cp P[|HS#Dggx}at9Ye"KVws !5I'>6 usV kid#PkK_yzavv" [ ^GޕˣIǹ9%1.BSʻF_X_$;[[4+mlW2 ^YgJ>B\Åؙtn棵4,GeF2,Ήg\L!YtXHH7`DPa!&rŘ7x[~ 6LbDPX*t3\.;xZ@ã{jdv4OvTV^i> '}^wm76'RZM C%⹋z9nB8oQRR^Ƈt(_ά;)%Y#Դd+sx1 BcߙZ6ιbY1p-ZŪW};uY6{Jf8aM aYKyhWaՒΌ B xbx]ƿ3CCwQVs4*Qs} E$;H9n)M)MW.S ^9>ŝ{ EѾUF\K`"~UV T'di87pZ1;@/EF잞 LJjvӯ =x<>fqv&`yv.F,k#PcX55tA"<sgFԵ8qӗ4@n?O^6VLj؏vA3&$}Bԧ[- I 8 w-6~>cXWv[6SLk*5O7t)&m[u:`(51`hygODo8n&;)_+G#5ȴP]Ƅd޴ [Í}f./Hnөv!{%C^".+e&Q6HyUB +nm× 23<@Nh4[*<,TbO sE{ـ|{Dy6= v&kYDCVA>U;pW1.2jS#6^z/!uZ蒯d惨{XqDBTژ> PUy2f>qe8X9^e?ycMQ. t;*ԖNb}o a0[aVa,us=^g+l54`ൠϮ{@'b$$>އQUޤbp =ʼnV.t"iYQh#8׻WMt5J:qE#4m?&1ԵS+nq,ô)+?G,Vl}%K?(xLSݗhA57,l-P.#u+Ӵ (F7u,Qhr9%2K<ef:x,UZuQtD4w" +rnj )x+ir / ߳aQ˂LPT2r{pNGvTv?4o6ײHL+rT&dswK52'd_XjHo0U¨ӻBȼyzP&E˜h nsTM&ԼKg@PSO6KޛqP S]S&i,NNLs x\[T!g 8ziZbx]z6!}|̐exm,؍CS&^ M4[j6@p=^Ϻ53Ķ\yӧ`WKlqE ;~"1t<£%4̃"8t'Csc2OTͭˢ.@Q@vtȉ)*F)ДFHDvqNpO8q>& /+ e J$ΩTI_ )2ʱ8v r:ӡNVk%\Whqge36%pBS<2"AUԉd}hy! =d\.=PW)ʍ*ef\NCB`ZY @_u0SLJQ\4iF5J29.V%Pj˅.NH 8eWan}~8|.&%/I+y?x t/h}s#JC6Nh,lA0O N5cr})`I 6Rɜ{Ɯ`-I{4??AcI3PFPog%IH('W6}L[̸cv WjQ[T%]~QL:j8|(?9bh_K[yYȐ}`3I{U쉓tV ~~S)>$]8T` /{?n¨Qڑd5 "ynZigs*%}))p5ZkL uT A"x}!qk tաBr{?Kپ"&ʾ}ioj֓T|/d^TGr1tR]!Z)R]F- nDxl*W](K0}ʢ"^tQT*NӅ{ ͩ嫘[g~ZNWuPf{j TEh{8Oԣ~r-q" a8G:_>EitVB$lcƶb僇bc44 jMy>X[8]%Ơ:Xw=cqB .]εٶSsW>(}6_נq*!PȚ6 8һSY5ŮVb,D !a1#9ٸ|1r0xM*4у#f )7y4~4q[|r>|3v J-aeNP_;ǣ^- Eepβ>k1FodقSBmY û~Mv>_1sJ:mؤGV?R0} e ^-7OA9@j?MRPH,dw^}-m,a o²bbb[%BB~x+ ӫ|N\<0֥\WrԩC<-ۺ!|R kd#,8}%fGFb&WfBYa#l * uQɲo$j햻J n,3<}1˩+Cӿ9EtMzD;rvTqcZ?s2qAsPI0ɾ>;b.ql0)C,x6i^bM؏~qRml[LWʡt7Y'•2 I)df|R ]ZsV6wԜ٭L\s 2Q߷3bzΘ7YtjtcRO A!Ҍ(~©U$^jN+h}=6pP@<+n-v&yB/0Ho. ==}XgTJ}wR(DͰ(P-GU[kuҎ& `Eeaæ.>9-ޠ-G!~ib \nJ-x*[vnPFŪGF?2,LsX'{u M$TV²ځOINgteӦH4nE&댛-l !K\`A[#JW/&]/{LVWC1>PZK%~@Nb@ ̉ϳ y3KgƥI@Ì&~H,}G 8t8D= ED"2 6NMj, fx4)C$~Q$}i#'CZT1'$-[}-`vVavq$f:T^b[f$_ On5:@[EXp0 *[d^`xFO vGCY]xB$ԍ2$z[>3 ܮ+) U%wT뱡4_Ʌ|*K.%-Qo׏w[{Tp=p;&DbNep9 ung.rЇmvYM*gB6y[dw4uK}5]):׼$yG+gƊXQ(E;iTu7vJe7䄐LP1~_tY^ۚrfr'>HE_\VVVA$?X xSGS`B_>ǻ܏a0WsXi34)e{8ae6$j[ `76"&9I]1,lSY]Ac^ %PCVl^wPw/.)Af֚54(q}*Nq{5Ŀ(zem<䐰pMThh T5$fZ^w66%Cw:#Bi)rd0gyI5KrjawḢ9lF,Si9ʡ/ ^L :vc,?L_˗ýp&tc(49WojڤX9YdNB٫\:xR&ݼTfz/e|Qa٪noI;XQm"򠌕,0bP, `:dERÚ{c:ǣ~y>S:)`ۤ(7s/@Vfʹ6,h܆ q;9BducJ g_ޛQOf{;쏩iz@}^KD,1.yd^l'bJ=fH.\:zz,=vT1eH!4A/h;A'mq`e`D Lɤ}BRҷ ʱ,Q2U F: GGu΂ӑ45Ҙ_V7v[/pJQˢ~%&;[;y3z[9(eҏYnBc|p^;";H5I8OC T'h'8eo>rz'N#-r& FړS^Qd\!!Ml:$R,v|mQlb.{߼v&>~zҗiێ릥ac!+i V g^A&'_o= iT)Ab/Z%*&Bܙ_6_-2)[u`#^~mbrFI1œXJu>f pH|@M!&@X릟bፓr@LcJVe.]ZQ[F3L[Qpc!Safୢ[EnJguvT7bwl,J8܏ - +L0;rCvy;L"PS4df[#/<0vJ`3'.p4SzCM+搴>FL7TZ*zq{+Қ6Dtޙ9mw  tAzT'.uRax/D<&YdC!fJ[lmPdqG#ڨ3C?WVWt);J7~;ghXEJGyɢ[._ue \) C 6j'=TL;WEU3(4YXF S&A7j~,3[r-zyQbߝ3n`\w )w|gteyƜK(gƭ KtU/!AwH/]at,\ޮ4+P "t/-sGU&8撃^.\oKݜ4s+ tay֮gQŔQS`!ku;xu)J?I]LVx *O*n"0i0|?4s!M- hn$ V%֎xN^*+I50e=r)O1Px07)F̅Ɩb5|FYS385K'f51?f(P%a=cUB!sc…vۘkN9Tbm\1t y[ٮۑ'Er>,bRS^jLxu&">'9ylTbʲ]c ӟZ,W?B%p{j|~ce\7}ާܓ(A,v<̓&Zpي<+?'0#L'sh*F(GmUD<чFx"tTyZQ|FiyFY߰njPf?w@._EfM_7˒ ""$Knӎqy.9m$O6vA7JVP&7TT/3l|A#c^hh/CsH i<׻]QxK1VXjT=A;Sm}'fM60+OR[A3b#+^x“ՈW7od#K]^uDɩ[(o~̭7! wYe|+!7VAE?E"q?Gc[/epA]eC߰X )@X-~0TeNz͟ҩ{&4<Kɿ'TWʌ;bK2ܾL隅oqWoktS:Tsn/i7 ZR䮷l5ogFgk71_cw΍B:|gy63JQ;Ɯ[&tc02߽1qt=kX| L5I `p;Z5(7\= 9q}61ێGNim8 Cf6]=0ێ!db_60Beȋc걎RvNylA~\|k^;It!>r$L*ʅ T &ZRWzд{aWE9Ǭb=SE!ħ6G1Ȼ7Cf`}DYY} wWVĐw~"$:<wT/X'&55Ό;8׌;(@"Lo%CFWϭB:JmlRS{RgMoQ0$9 Uku,SY;C"m+./caߵ@F|^ $235jN9M\9}O | k9 o0k^+pKҺ1v>o{Uk_U~h ־Ph+VoF<[L@"32=<5CM#@O3L<~؄=O7@K:sd>pkͱ1FLk 1EtbK$bbeb"K豑G]B v)̚T7ڹds rGY{؂ KJ:RkH%|/ ' C6v`T? >&ǬyF pDΓWӫ _ߋC!\?}وF#*xj+=J8!| SdšZ)LuKgkx 1ۥRGS."/$'M̶\\sIZ1~>L0n=gi8u,鵥/٬oTh/{.%e+.OsqzWw~&hn}+6UrmDm<l9ಗhR^ ΜȢ]ksX6 i^xN$z>;՗G??av`:-Vpވ(ߜE~e2|'>3@ĈAa֟O]aƙeꐧ%v/zdZ4Uj94` wi-MRƣ9#S5c+qR=-6+*]Ϥg'r&SDVkטѓ!ItU[^]?#X>l|`z2]޾Vd>*g$]C)9w’q 1ҞMI=mߔX z;#am]O[?"pTj>&2R kڍC.+e_RX" z'ᨷ*`$?F1i J1<*R="(;laR!uzk/6?~ |=MHp" # 0~$c53ȿ"al\nHvBvwm*"'pKɚpqGVfB}# }E+%әI.A?I 3M]q9v&|81 7+mP=;hB*Oqn -qRZ',o{=eV>:PmAPΐ qU0uܞ@;؉#J?93LXM;J)RV ?ːRJV)SW^^V4xrM*uEIMr1:'~6 ۈx7ICe3ZAJOԸz59(H&o*ed>|}`c\+{$acY>uj`ϷVu>*Įڲ7Sc\OVL>B}%Q~XL_i'6an: ]N~ڌK+5R%c_QmLy|dl4{T\ti[ⷱz~ ðjybS<9A;Mb}+p2j8\4nV"]7[2peё Y?eqdҞ\X5%n@8g{o~;eE?7\&%78 ;^D|m[h\Ӟ+6;G[{$]A9Dow#8um|[]Mux|׾q r2a$"4ȰW:ҷ0;Z"xvο($s 35c5&0XsL<< cBR? M3ꓳf߻DB5dddĈk]6E:i#L'Xov/HMuף F&]L""(O#'o?l<3t=OS1կ=o*FrUnDQVdM8$=J#ܝpԶ䛄'>+;T5}a> 暪J"J϶IoFA|ZNeX {3"?Q">ЧD-d8I΃E@ > endobj 487 0 obj << /Ascent 611 /CapHeight 611 /Descent -222 /FontName /TYHSRO+CMTT10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-4 -235 731 800] /Flags 4 /CharSet (/exclam/quotedbl/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/underscore/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde) /FontFile 488 0 R >> endobj 1117 0 obj [525 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 0 525 0 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 525 ] endobj 1116 0 obj << /Type /Encoding /Differences [ 0 /.notdef 33/exclam/quotedbl 35/.notdef 36/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright 94/.notdef 95/underscore 96/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef] >> endobj 468 0 obj << /Length1 841 /Length2 1173 /Length3 532 /Length 1775 /Filter /FlateDecode >> stream xRiXSWjA$!(`bQ"zInKo R",jYX RAuXGm AP>89k~i DnA'?RL%H, *q2  ҝlN4:Pir`'jEDbC8`Cr,{p rXA"pxe 8 `4%@"9  SCK.}M1n ؉p\T"0@F`"7$^ixH"^)P4\c˜d"⵬!/ОL$#xHⰄ ߪJ+}"DHaFZoj<% QT2 B| Ys~ ">`Ks " + +X;%<#aPD(e~[A-@ ,yv};8G(A2*Pe-a8Ai1!c,>C<5JCB9{΅eW$9va?Qnԫ[XpciWEcッ=_awLR?XS`TJ$0,OOZlm9phW7;`C_^pw3M^Ꮊ>XTwou8c)[ĈgVntLyyeɖ<P ;a7¬T|}nYMr,"4r>9vsT#.oI)>z3 )ig<04d'մ;}>Um]6RiװGn_R DoSbȇ*rOU5wUm\;{YiKWum᪅JA88DzNJݰC]w  w3D"ʝ/)?xU]g9"^=@dW%֕bbG1Mᩃ\Ģ=5Ji]9I BftzWX`u1(X֮OfawDЉcz Js?`|2Sf>.LE;MgT3樾畖>9k"l,?PXEux/7ݡG}o`}dNyBֵ}5t}'@ü"֩u+AK^-qVc>?kN<1RNV}d֍ЌOü/tV7f{ȥN);T~14$OOj "]/z27o>vYZe~fL{ž D$ă(j;s<6(vO{pelk~i3徧wq> endobj 467 0 obj << /Ascent 750 /CapHeight 683 /Descent -194 /FontName /TCZMGV+CMSY10 /ItalicAngle -14.035 /StemV 85 /XHeight 431 /FontBBox [-29 -960 1116 775] /Flags 4 /CharSet (/logicaland/braceleft/braceright/bar/backslash) /FontFile 468 0 R >> endobj 1119 0 obj [667 0 0 0 0 0 0 0 500 500 0 0 278 0 0 0 500 ] endobj 1118 0 obj << /Type /Encoding /Differences [ 0 /.notdef 94/logicaland 95/.notdef 102/braceleft/braceright 104/.notdef 106/bar 107/.notdef 110/backslash 111/.notdef] >> endobj 450 0 obj << /Length1 1912 /Length2 16098 /Length3 532 /Length 17186 /Filter /FlateDecode >> stream xڬcxͶvl۶ٱmt۶ձNǶmul8_^kc5U5c)( lm虸 eU$ ȄN6"NnB&..fB1/7;7;4!0?Is#BY'3FVʶF'wzBA++Bp$T8\LLFNSsh/ B4T00qRq23"9j1~V3tKLƔ}'1阁x:@[` 'AO$fa#dq6P s2;~_e0+#! `W)edkmm')fng#짊!ٟ'!OӞ 8ۧ#'3_TO `gVܲ}:3?Vƶ?M 埪i ECCDЧ迉SU}JOY?'>dЧԓ7q~)O=?>7^}*Ou?>5M\zF8{\,lX NԆsj?Wse?srOAӿsfb{ ?=Yga ?]N_/t~r ?]9\OW5OWn+ӕǿmBBntLw~zd'bL#g>wgW?61lzyֈ'"1䧏ht)8#nڏ4 9) R0ybt Vא2C*U^2ĥѩ.p`/uV2] K'x1G>yŅ[K߉eTcdh6$fmr0v=2V\Wd,|W(F*7 h Kel.C"%98?,f-Q8 CdmԻLϕ1'tI,|9a|=uH1fΤhxJy5)z.o_`@&=wJ aZ"JCjqrlG,G/s 'G@t/] lIf]#ߒ@tYy:3 nL)_+>+*7ԣO3E&M/&xp ΃cg=#s@l` l62˖Y4~+ݩ+e˲X`dΔWf) s贁AyI5܌juMnj!ldÅzٕW>!vͩn01)M)TwyCC{V6H)BFq n7/n<$i.3AY2CjG;R%1MXhi՝=w̓+ESzO.e0|3Sd 瘎J3B[?Yx8Rw8D sGXƄSҌ>o_R0#0hǮ=jQ9p&Rx@l;^2ۈ!uVlmJ!6hvtbt/d4QsYT4۬@%-8\]O9 G "m>gR{)?}i쑭F"f;=5 i^j\P/>F=\P+"HsLP`͞@ H":#nޑJ)2{\̤H.EncUl@`IR]/?dcTJ@EbI!5~ #KNF`B S<1z*·ppͼ/Ghho02$r_+2FnM0pYL]_oǣ&`e{^u);cV#d4tbQ}5ZއcW-`u{ZmEaGќ=&o߹+ jnSd%uZٸ 80ksIo}j*ߔhi7d$PR$^+5&@kB2a<8GPZSґV1D]n ڂ{JT|PQ<{yW7k"\wDx 3˝X5G\VBJn8R\b↥g>W@dS/!rVW >9<X3fr8gdF@^#P/@`F٫r#M\g0XQwP8K`SJ*ٯv;28PؙMpIѧN_uߚD*4i49{LP-,ݗ{ֶqPKWc B4i25q=B:DR9d۟yG}2:u&B*9^_bޣѤ'"GfW]XIC5/K9FpO.qJ"rT*i4~W/\F)NF֪Pi+9g=ЌrZn5kxG׵0~@w#@Eo٣E_*τ"3౱< p5q}6eٝ—MʋgEta\xl }n7ԺM-i˷6.SM9/G5Ɉଣ(7a 8nkdYiG`o/}ďRv9Vz6da/SN+rj~S 䳝7;GE?|% AO0zY8qפf9lilyoܘ B8;XXAd̬NmTsa yEcۓBvԐi{ j?_1^ 9I /sѷP-ە럒3 r0``u_HQdB˰9bB9}4NS, %kl, ֆc/Zq\!N8+{~3т^M>sɨŻrB7*:T8kNh=JSUyʖ1DxkZCTx[f2t)߸-@ 4;zrd H'Rs>#!9: g_ҙjw ȅgA/bPmS43h)6B&LS ۂ{-;$E bEWրzL/dԕԯmK@(eM x/0RQU^ZoyBM?<k+;MN#9@s!Oa|f,\W$+~\b:9[! ӓf|wE\:'`W{h|0q7 {M|@BPA>Om8d8%RQ4.F6JŅ~'84aa;;@LZ~{¡dz 쉻ĄUnD7)54/5IDC?Ֆ*B( A^<-OBtֱ&6l5x\!c5 o@,@Z( ClcKxdFp:ԅE1llEϡޖ0x$ ڬ$O(t߽a"٣`?Z?5ja[װdxB4ԛ2/-B .`7.Pn axˎd!J'٦3%?:[zVqLȧD0 Og$ӧnXB*~o#'/0s@u|d.x&~8}NA8+ODvw|8[""y h*59k։تq:.֞%Н>t٠q(}]rH<]cf_H`Aj{ae%8 Bd*nT"sc7N ,)j(}XE>p6!g?fx:QxғGHmI|z"7E{r詈ʶnI ouxờlSfU]P-.td2 E)(, ȝۗUmna[2Wa)^J>Rvr+Kaqc?Vo8w(1s^~G^?x6"jf8ZDF Oe(D+ƺ;~Del[cN YMy9gj/emCGK9=(.y"Ik6HL !nX45wq4c@MV(V=k(l.63-*"UWD5E3?v6 w]DTZ=!a.9'4(E (DQ@y_Byo?Ӭ@tgNt] 9yK9?LT'+6WurDC| mr6~|jQEA3j@! f@2ZmȚx 6YoC) S;*'ڱcZYZkXRlK :$*pmv!Fba! &E%-T_)iYko "Ó=|ueE;M93K9xޜ\yw:|gmyմF3zz klq|4 oFzsoK(W~\AF5:A_&]]/Ft)x)7?c&”.2Hϰu{W!-;qNU?!' f$[ D7^+`DTN0Ôo M(#([A߉qmKZ Pe&qo/я)Πr%.`Ȱ$?МDgN4Uc\eXfHv~͎~8FI^;ECCڙnM=oag~_fUm< 'D_5ƛI2^l<9sh?s#XO.#Ŀn׮*g~A0\/YIO8N6Xjt `CQ[ӋknLP'XB5+U49=a|O;0EM ԡ\Z!)S?T^q`&UO%c yn(`G Yw. i$0% UD$vNȥpQ'SR&]3U9KqG',1hnQtHyFrO>u*0!{` MAcIN(TnogM.JkQhkNTAx bo1:r&QЗsN;D{>Z Hpz2=j{X@:f@8;ENdKm&[` 3uFT'.0=1rēo~Dzbt ' 9Wgi]R9[@qkiOP uxɰ68ҰB]SVŲC] //% , KsDT :}2":`*erh\51G]CJ &e_ˮW]PCZ f ^tXfZR܉(A3Bwp2)9A&$rto| ^_i/n$ xa[ADŽ4mAOzCeB asEl%Iî_}Ṧ6$"trn#6g[d:mA)S"agZN.@Bnv[ *lU?BY% ԫ8}cyF" }街 a*Pѭ^WklBŮ~@bNt( *SAS JxӤKvhtM sGG!(3V'a06i\4؏e,!K6TIDSrKh*%1}St.] ,6}=e΄@+; gJUT$i_9ӌ. U[e.B4Oڃy,T &aה[mMrh{\/}_i~j䉄iG8ݥ S^ݩ`l A޻W |3n3a04-14aȬR24ol: t`͆AĆT XFj8 E*u4Q#gj;~܀2nW5KnŮľB}HV!M@Mjx¢ż2C9EʼA^T.w¹i)MHa}r ك? M[uelJ%u̔$VnylW<^#_# ʅTyo/>4!F jCi$'%F^hB(Zi.08NQ?!eL`qpl{++joy/goo7Auj'پQ u??G+[U|/z[Lb&8z0OqCx4v׌"NyId\b~S9r@{< #XI+6?: p䜼Ý׃wYeZ"f2*_;n=R X u: 3!6{ uq9=E:YZ_εh.PC X]N#%: ոg1_\bF z} Iv|2O-I/@(Po (r#UGv%X%0@r#+82Ƶ{TJ7NV#(n眳_; > {'8?!׬8Ñ_ed i૆XLˠZpV̗GbsͦSkrɊ9iylD5& E$frEEGibmHqHS 㪖D̊[#b߶ 1S]WMX| 0ZBJ۞^ Y-~J_* V.wU5pw})c7}NZYC@Yno7OcBqP ?SXurUMlf`oQq獩!)k$+-fmK6ɈT;maW;C 8J#qV y{褯AAtB=4ESw;Ŀc`=PhX,-4 X6%&~_ ulltDzl"H<īI84/ew ` |_>K{f0P E$uis* 4)뙱XÌ:ׯǩכ0sjD't>9)K' )ؠg`WLVC.8V6i|uF ԉ%bԕT15keu<k/=~ IilS(EM̪(̙n!Lv.22[KT7×Rԏ,Z=g3,鬸)voh_!Co?osHNSÝxe1tq "+6A_ gpW2'xsCJ:|-Z>x p)gSAC{{sB  L̺0K^tWa 51jj}ZXB+ɲyF'bڪ>M=eYO%q.h봷I#@LLEڅT&sԆY*%vZ m甚Ru4X>MTHda` #  ]A7AoE$WTNJJVL%yLO@TՃϹoma#T\,n1 w *vދ ]P핊ݾͳ$nI_6Tbڣ9IYOZJk$Opԃupu|+W$MH v1Xn:zE+;T 8_͢}GB3@9[xR#.K@ffBoK xe^z @.O'Z›JaMV\*e4b/Ô^Obu[: "].G0  ˇr;ߜ XeF '!~5}Qt]W)0]}<<,A3m۱չz[GP )Dw %Mn1DK@ azI!s7%f0n#)8tx㐞XebKt#5!n;ȏ݄jǣo35"ˡcV*= 1!X#ۄ{wCu:&'AUcAU(dvkzzL*0HޮɃ0KbKD}m,;W2*E `FRb KBy*cPSD^~KK_וD{lwz"K=j ;lqΨ|LЫ$Z6h ~ǝS:ӖEz!M& #;-FLe$# P/C8Νʼn,)[T cM{ZXlg~uh$,; M73%e*x-!$8MU7fioa7/ {ܭ㝊_r* +u¨p;Ƕ^pvȱ̺и-(S셵?!Co*Zd:;]!hjz4Bʯ6oȡL.Bܞ͙fbf?rqvútށ6 xx"4 L㻺[<<s)q7+w#Ro0lf&mbR3]6]d UuV]$'\b~NM4>xNT FJ{ŜJjF97;-"(f ,[-qfHSiT"%%bFj e$i֥ xAsmU֠qQ \ XKCv5U_6i#" *N߳H RxNPuc:Lsi`ʣ ]UO2`4໛()ɂBJаu^QlPy"j&=F_k~cNZi//hi.jV1Eҵ1o+̼tZ7@SV3\yc 2IR6Ɔt{>yF: /ݷ>qQ, _pq[mqELڃ^& m9'o襏|foT:Z7g7}MQdcm6ˉ' AS8za~<#1%omå;ɠr0Ě;>3ʉY @ iсq BB-R龠{;~Š!2ϹN~]W| 5+jXu&ѠvߔpH{"N.I*{u&0cw:[ksl:,s;5OƺZYՎV6v±%oT]lo5Yk][+NmبǓ]p0(fy#V{3_.&g2E]сCo2si/|<%&_tJe9nv)3eB=rj#-fu4r5MUCEu k3b^kԀaa@rNjbQI~nbQ6!1endstream endobj 451 0 obj << /Type /Font /Subtype /Type1 /Encoding 1120 0 R /FirstChar 11 /LastChar 122 /Widths 1121 0 R /BaseFont /BQAEUI+CMTI10 /FontDescriptor 449 0 R >> endobj 449 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /BQAEUI+CMTI10 /ItalicAngle -14.04 /StemV 68 /XHeight 431 /FontBBox [-163 -250 1146 969] /Flags 4 /CharSet (/ff/fi/fl/ffi/numbersign/quoteright/parenleft/parenright/comma/hyphen/period/slash/zero/one/two/three/four/five/eight/colon/semicolon/exclamdown/equal/question/A/C/D/E/F/G/H/I/K/M/N/O/P/Q/S/T/U/V/W/X/Y/bracketleft/bracketright/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z) /FontFile 450 0 R >> endobj 1121 0 obj [613 562 588 882 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 818 0 0 0 307 409 409 0 0 307 358 307 511 511 511 511 511 511 511 0 0 511 0 307 307 307 767 0 511 0 743 0 716 755 678 653 774 743 386 0 769 0 897 743 767 678 767 0 562 716 743 743 999 743 743 0 307 0 307 0 0 0 511 460 460 511 460 307 460 511 307 307 460 256 818 562 511 511 460 422 409 332 537 460 664 464 486 409 ] endobj 1120 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl/ffi 15/.notdef 35/numbersign 36/.notdef 39/quoteright/parenleft/parenright 42/.notdef 44/comma/hyphen/period/slash/zero/one/two/three/four/five 54/.notdef 56/eight 57/.notdef 58/colon/semicolon/exclamdown/equal 62/.notdef 63/question 64/.notdef 65/A 66/.notdef 67/C/D/E/F/G/H/I 74/.notdef 75/K 76/.notdef 77/M/N/O/P/Q 82/.notdef 83/S/T/U/V/W/X/Y 90/.notdef 91/bracketleft 92/.notdef 93/bracketright 94/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z 123/.notdef] >> endobj 1122 0 obj << /Type /Encoding /Differences [ 0 /.notdef 1/dotaccent/fi/fl/fraction/hungarumlaut/Lslash/lslash/ogonek/ring 10/.notdef 11/breve/minus 13/.notdef 14/Zcaron/zcaron/caron/dotlessi/dotlessj/ff/ffi/ffl/notequal/infinity/lessequal/greaterequal/partialdiff/summation/product/pi/grave/quotesingle/space/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/asciicircum/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/asciitilde 127/.notdef 128/Euro/integral/quotesinglbase/florin/quotedblbase/ellipsis/dagger/daggerdbl/circumflex/perthousand/Scaron/guilsinglleft/OE/Omega/radical/approxequal 144/.notdef 147/quotedblleft/quotedblright/bullet/endash/emdash/tilde/trademark/scaron/guilsinglright/oe/Delta/lozenge/Ydieresis 160/.notdef 161/exclamdown/cent/sterling/currency/yen/brokenbar/section/dieresis/copyright/ordfeminine/guillemotleft/logicalnot/hyphen/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guillemotright/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis] >> endobj 447 0 obj << /Length1 1630 /Length2 7251 /Length3 532 /Length 8105 /Filter /FlateDecode >> stream xteT6HwJH#(RCP %!) )1tsg=9_ٟZl:| P h]lzP-pccS`(Dl @X $))Pz4]6G !ǁ ؁A%mgZNU-C*Y;tm@A\;( B!߭k߇ &^+`8f A!@gw rA=\m`:P8]:*ՉpF ߛP{O[(wKl0V5 @^߹l@[0>=+ w8b x05cο]]DCx0r DC~3 $6π8 }ֶP7d'EܧpXoB?={;ucG3 Cl b]]߽@߀=CXߏEbO _J0\#;kBlA0g0tퟱf3p I{/c_?:0v?фS  K%}A¢~E?@B50oA?_`@P߫o?@w?f@PǴtD5UN߰YWz_kqAa~`%= -{0Q&כu5n@3G~+Wg>"{#dE1AQ2sʰŻk,fW G~ SWB`x:ꂝ]St:`c񧌟'|:V&Q\/ˆ~plU4ѽތlu#]xﻴZ9D}Z7RmZ|;uh lǢno`[l`lg~Mٔq9!λ{eyV$i>%F$CGj!EK\{3BA^-xf 1k6EcpqI_3r9o6'g.>yF_C2 }8QuCr Ĥ+BS5jaJ jϞ{0`:2dXhS}KҨIT#tSw@IH|WͤOhgFq)!'f8U%+/m']25L"ֻn_^uFZU9Lv98 JgxkՎ,;}U~jTH*ẖkkxChx$Z?!"D:`>엨 ˶ C׍S7*5O铱)'aC<_Sʯ!c|,A`'_ְa'o-lI5X_j 3&' E-7|6 3GE᪲dl$v3oY## f1irfFyIVWfqEO._H3Ժ/ͷڛ.~o 2ItfY& ww b=nD IF:|jU d{y"{O3Oۅ|j -V7F nHz#T炎>cϯ`Xdt iw m+ KZ'=^[yG韎=iAJ>vӛ@9ٵHT|kK4dwKijGv.+wn硋f- $*ƿq _%.v]yD&jW/%l3- ofIXlͼzYc)a5bEɴs<`5U]#GF4kff*]AU'/b8Յkia `r^ 懈[ bq( "]W8z 4:3 鄴 JD>]E0MMDSeS&zOrpm"4Z3(ߺ؉ވ9 7ɵg>\t/ۉѺ%^$G_[AGua4 gC tF:/A霿p>bA}`ܔFzrX)6#knu SGMP@Z4=a,ZBSLS_5y8~&gc;cM֦L< }ʝlw:<ӛA uQf_&<x.apж4 s.f(Z<_<"RICLJ,4nwhw!6{Up{qQBT! cu,}=_zTd,sKy|y"gͱ${ ]CO:)ele2:Q6l%+֞7CzT Ǜ]i"%42ފ:/e\kFF̀NwQVy8pTgp`|/<yN%b~cK/ Ȼ;u+۫꺦2~X Txk̭շ; g"4S'|>%yv9_Ҷ]+SmR`8OwHXQl,lҩo٫YAy*ˋ^<̡\/P0x|.0ݫM<23EC RnOמ\EF7=&ȌSM/\_ m~46u`/Z> FFJ!d`'|˨u$3mԿ,5'5rmvNP8ep*Oe5[d)![9<-Oxq=^=}o.y렍 W0cۙ6~$%j[/IC['N V'~m1)VX* g0MA9iS.F҃+3!6Q=U|63v̫ ћ .h/y޾ң/؜tt'8Ш^J1nxcԛHaM~ خMWţLJϳ+OT˿8Ӏgwl{k;%K'^yB4w=R,^bv%~B}MmY]1VNo#ulŷ,ɞCW-V=݄6Ci[]Ph9jVY ΠMI މJ^>2uy0 x l>J)(w <%*Z4nKޠ?^3k+NU<$t 栰& jإ`F4ͯL #oO"%幻ʙr)2QQXfҟ-}JP|Q(=BYddQQߍ=~ui ɻS\ٟaѦW!'" waߏ, 1b4<ѫWsFj塼fbQ/IK')ǍIŅf'JX,~4Ru"X6'Qk5yV ^.%JoBW1Ss`Tֿs!.Lԯmez6 VH>=Q5H!31U\iɅvIWFf܉u-zs8^j]p\L a:&CzǢd6[Lv)_ln7<|Z[ ZG,6w{C|Qܝ3v`hд}֋q``lvI]7۩PȁCZv_}j1X|X.aLO_t8X*Rtx·FG͓YYkBKmc@9][t0gX3;۟, He.S޻@j.J$3϶% /'\__M& ,$їOF o%hj҃;X 4KkxO7?1 =NJ@Kw7/fOn\W٩wתlPGCX UlRRԎ[N%݂TԈj4D./j'2b&c2ЩM >gZ7Y6֞//0f`ϫfɓTIPU7֍GΚX}oqn0~^jJevuz/WcI4~m6{Mr5kLK>HVpO6"T2ӾrR0*_uMuæ$l05\7 pW2Pf ipK-F E 5OCaݚA5?#mN(Ʒ6?eʼfт۱Fip qCt~'bC/MD#fσɚ*;(\ϻ ΅ׁzqb摟fIb`wAoRf1Y>FV*,M}v&=6܌p'S}ZLf\CڲTI wB:cqQQn._<%o {N 5^f;Αt>VSub_Fa#rNXrlX7AW?>s^tޮ2X:<擗R617]MyQ#"qx$l$n8pgP`-1%)&W#37v6eȱO|; h)iQm虬mi bR 5(،~C䔕6a oSI]*R TXi=QИB֕9򗼵yifG&lS A-nV~ NY$hCCk|sޟ翿ϯ~ NCJ֯z3_TE{k#>+4|5Xc0!OsD/ʇ$ĖGEOKs*9DJ볘pm~IbNPSKq>4>//ajW:*jG昐6 zLn7~@u<|</ZU27&+yd{U¨b' a1 +2qyɅ9"cn;1}.TJ^j~;0 Z"!>t<UҤX>rha1הe:NXiaQs'=j`rD &5u> az׶O'bC_X{M@=p 6Zi}9dB@Kbw?݆_/9Dt<(OCX;yv Ԁ2v23N^,l{yBZŀ5 qז1/w|kCH-%>~5-dLLG̒tgid#Mr`$K_>6$㧽߮!(,O~p1ޖk1;@li,`a5y?KopBbTZFƎMAeLق>pׁIn)#n~=Zcs 첷9cb˩ ]V7^ 0LJ;WS3)> endobj 446 0 obj << /Ascent 678 /CapHeight 651 /Descent -216 /FontName /FPXGGF+NimbusRomNo9L-Regu /ItalicAngle 0 /StemV 85 /XHeight 450 /FontBBox [-168 -281 1000 924] /Flags 4 /CharSet (/zero/one/two/three/four/five/six/seven/eight/nine) /FontFile 447 0 R >> endobj 1123 0 obj [500 500 500 500 500 500 500 500 500 500 ] endobj 444 0 obj << /Length1 1166 /Length2 2469 /Length3 544 /Length 3252 /Filter /FlateDecode >> stream xW{wT\ 4ЊFei!h g3]qT;-0 @}LE bQ<q,Fx @"C>F~ 1Ѐ @Ƞ@TeAó@*˕MS 2ild"f4z8 UwO5   xBeIXT+DY Z*Ţp:0m&Q jB-,-hM [bx^S}#SiԈDJMS`6?< Y>Ba` Ók)㨄:q& Aą##; c΃A׽=ŀ€m +?ށhTJp\-l<-5~{CIj! -C}ޤuV7N8?u"~Hivx>~k)d0y ~c54G@H9BW;LXsc#Q兟=?e(ޜ@nĴ@“7 _CЉƄ־d@ s#Ax2d2ygRZR4D \Y1߁5f0x|9 ޻DW x4['jKB;u?)7.^lN2-/h/`hJ6i KIH o.3q@ϊvCߒ|zsj+lx[EoSlk,Me` s8OՌV8P{Z OWvm#V9$ͩ: #'ƺ5}}^gTPC\)m49@B3D()$1FҀۭ&2}b.cv;<8Nۆ ٻ7$Mp2w{ɽyAN@IX ępn{ Otw;,n<'bb]2p9dOF{;z/ưw}&MZJ"+"%c2n+Eb$ R":<% y}SpFxlf_`ͻ[Ok%=*hl WR<[òyk>Hh1ylyO1RjcH3vrǔ)rnCRȩ#" ̚v^<3$!OL7sj,ψlH1~)Vf5ڝ%9Z:gI8=ֶzKY5w'ոuݽVK#P u?Q\/V դ9kg_ rn>}3$Cb󺾫*=pd=nޑ}xDA) UΦ)J[CtQ.Ӭ \vLy_',R9r ಓ?%mSl=8o`:M*azJ`eSdvmY1m]isMCɓ¯59(1(+zUpl *#$Y[t^Iy/\Ć'NU4%ǸP6zy}^Mөa#P*ɶo/56pe_OԘsXY$V$K|_Yi/=QzѦg$j%}uj #\]-œ~(L@'#_;s}9f-dbu/}8et 1;a>d5J 1ְE8F[C6Av2BW(bE}ktY"%m&(Ub_h`9_?oZLdxa]/y&ۉ0Hy8pk3y'+/QNWx> endobj 443 0 obj << /Ascent 712 /CapHeight 712 /Descent -213 /FontName /QDHWOE+NimbusSanL-Regu /ItalicAngle 0 /StemV 85 /XHeight 523 /FontBBox [-174 -285 1001 953] /Flags 4 /CharSet (/A/C/E/H/P/R/T) /FontFile 444 0 R >> endobj 1124 0 obj [667 0 722 0 667 0 0 722 0 0 0 0 0 0 0 667 0 722 0 611 ] endobj 329 0 obj << /Length1 848 /Length2 1318 /Length3 532 /Length 1944 /Filter /FlateDecode >> stream xR}8TiWIJDĘ93 ɷ 93;s0m/2nm*ҥU>dc)җQR*Js]9{~ϭK⡈3TȔn baQDt:}}G!(9b |1  bZ2YD|btf .!@(G1 m 8FGa1PD2Yv 8&\G9QqBFC/yV'( !hF d5r1KhG?>(' rqL?߂(9:98pőX"M8l?p8 7{/@}6Q1F N2ߎqo\Bt'_ʉ>BȬ[pa$,J& gqh>1E1>`,qrȈ@%E"&eL1 [@T4x23  ЈX B37b_\NhC^0!D ND_9.{ &i9tiZrF|Zғׂ bC9%.\Ux]Ժ׊\`4mu )[Ҹwԍ{7*Pz\.^ϫ5ȕy v e_lp$[R9Hc\i=WW4K?:vNZF 6 /Ɔ[%Q?3̕xS :YՒr^-Ny2Kk괒X+D^\]]o,k%x={z|clV.ҷ?J㊮ I;wKevb5&1U$I.qclRUiVCgw~NhWɠE;܄tm;JOm4ȼxPI|a0|$\ڛ]vzxkxPs:=T~mp] o¤&\򄂖_YNTC 8x$,@endstream endobj 330 0 obj << /Type /Font /Subtype /Type1 /Encoding 1125 0 R /FirstChar 15 /LastChar 15 /Widths 1126 0 R /BaseFont /RDSXST+wasy10 /FontDescriptor 328 0 R >> endobj 328 0 obj << /Ascent 741 /CapHeight 586 /Descent -1667 /FontName /RDSXST+wasy10 /ItalicAngle 0 /StemV 25 /XHeight 431 /FontBBox [-23 -1667 1720 881] /Flags 4 /CharSet (/twonotes) /FontFile 329 0 R >> endobj 1126 0 obj [722 ] endobj 1125 0 obj << /Type /Encoding /Differences [ 0 /.notdef 15/twonotes 16/.notdef] >> endobj 326 0 obj << /Length1 1928 /Length2 13850 /Length3 532 /Length 14914 /Filter /FlateDecode >> stream xU\ݶ{ݽw Z\w+N"ݥkos$3si 5Pѝ $`gacGp89J||i  jce@jcnP2u:s4m,1{{?=@7+h1wlXqst;lߏ@@W7_7hĪ vC&W6u'f=7uN@W6[N #njoc.he;d&mPq7Xڻ:ZOKUU^ZUO_UMm5b? W/>xz f?r4wqppqL]]ML\_v 8:S`ςל_#m '`7uO=hte迗?apg{?Vs'?.5O m,xnn"Vӟ{yVtvڝ<\W x]`Y7 /W6SӟN`韉'CPI!pR!p<+!p..!!h!h!!m\=,|Yٖ|tf!a Yοm˳ [:~l mB_ V&;au VN!/[`+׿}B_`+Ͽ_ V>?}ˊ;y2sg|fji liځ@/9ʢ@mZcxTt9,USr]\rr}ɨ fSE&6o"v? AO u3COS.Hͱdt=Pn]L{ZNrutO#6<1a6Bm#׮= ^!ᢣ?-#l٪a =aR{^-O#DcݦBCڏ c5iNb4ϡةBo ofߡZ'fwmD6E Gg]$>V'~ ڧamE;In9?%=P@yRT ҩMG3-˗`{ θ@LXΨx@*9hʲ!a8&bF`|KQ--|Ss "l֦ۧ]:̀P{t~8R2]>d+1Ezp,ؓJ?66B5>[_Y!wCF"l?:i,}ac2͇'q#6uB-9-T4mèE?qZ؏&IЮM~C!wS舨 2̽6weΩU`~'3DS 7؎ߣ wv!/|GTB+&Ծ+vm J2Rʊ ؤk$ ;0=2D>[iyO0,lD@T=GܝOޕ%T4 ]wg?bڟlk:ےPyv"L 8zat9 k60(w[.%4&%y.~'_O;S43918vޭEﭓGPqn-s?Jg|(gU.tG /D@dPed'/il$k6H$K{S9Lބ*_xs,rrFqӬj>R;;Y FX ﷯$K1̓}UĴԼ]C>3ƣ$ANN;wiS#GV12>e /YVG`6b(`T B5CR{fW:F6ni{LAL[ gݘ/n i\}9Ϳ,]Q`? Y͒EiӝG\X(Cre)H("a))Q2?XWU^015n95lt F9[d,MB/WΝ"?5gKg?!a2톧 K |x msWtsjL2 R'^Whac|aXNiJ`%r /QdGucm!`8Qn$2S|$xCxКj;xÜHziv5Zcxms˯1K GoFXj^cOR$GZ$ ;$"okPrX^OytgtE Myї˴ELW\_(Zܿd6q N4 QxP^W\}^Fd⮧+'iXwr6RUhj~,_<[s>5W pL1Ě*qȌ 5 ޻EZ?3;#Bi~->z#oz'$‘Hi2_#']j!yoo,DmGq6.K\D"')vƷrK?jNZep]fYxL;*GGW~ %{,k:HtyiT{tg- ?g?ˈYrpТIc+y"}0MKWo,QzǙ90lY-֗B#թ ԂTI7ƿOݬTx6%a6{Vol aX_dPit03"v HbP_jij:w-?jR u(p$YU8=A3}mlǷX@Z\PF>K]x\4vZYҊSβF}.dyELկ>eK.1~Ӄr-A#r .2j$ՂŢk*;F#8C]ґhYB[@`63Px[\I,1+!\Gz[$8hWzq;Ex,F9@f){%Cz* {=\^Dt[(G-Wa YPGNPd~{t/h)DJoȻ?=o˜QI*IJa+CC h 8AoBQ?3IgF^Y)5f.+nDe$bz3Cڻ5Q |kkdu1e2Q&s^ (d$-hqelGK$uÜTHcg8ݓ7-YŽ U4# ȐCzq$^t/mGj]nVDRiPĥ[ͬ`/[D69vRW&AqswB,ILەos>>HЗWਮܐ9Û6b+!̲8_ªNhYDgwri(@$f ޥ[2kJ$G-wo^;EE.UIB9qUOr:.(H"*ec&꧘>ב<^j@Ngu<=y)Y19,L.sF6J)&jE: 6 g~DO0"7Л/]f;+9,V$L~(7iE՗NlƒՉy7@^+xcu/T MƲD NkFD5Kg1xERqo ߸|T-0΍!'Y댻dO*oä 6OSHVY%YGX{ӣ%(ZHѮSھ<%kD,'v;>4Cw*JPOZPMW⎯{l匰*3뇠aĂ҄76I =:LY=M̪gΙp/H̅VOJ E4$yq7h=2]"%\R>8sv62WnV. e񆷍vʥZDLX#@]c01^ߥ!9A2*E5)' qyhj#6vN"7%,r^ޒXR}W y?n}2hq}>~Uאͽ[g?w#@B Yƙ (crd++ӬW}k*? rL{ DmY5t(m UVbE6Rop,b9)p`ב8QDA=9er@C鶦LǤ뒠D`lwGwүίEv3M0ݴ #RP^}5k.!p&|&"sfyoAT:y)2 + #m!%rjrK|[ڄ~MIRK mEQfidNNjX֮P2y>Z&Uvm^6`i&(}`fahxt/8V/_+qL鷨7wux:zs0’1.3RrV(:y Rٽs,ASwK\y`+'C' s'[l3oZ'?n?]t@Z#ʬt+<'('_l(IL'3]8Q3ʷ(: C`괲Y*0m 7d"O?nuK)^luH.PDGܡC -~yN"YD﵄& kO`ssZE{ N^0.hg[+~KtJu&[̾'*$dHa(F/bv+0+yyb0Ik5l50_œDd"av,ç!3?]&e !N7kw9O9>~*GGoGT 獒 B_FgK0 >ӑ0>x,D͐9?&u 1ׇ ZpX:4I`7s4`GI޲Hh0^֣%F,R>MLGţ4GXq.h`45apT!E[:V ɱxVGO]$s.VgbG J\iR Hd\pE{ W_-kƀQ4Mz@"},a)2|Jf#徲D> gjWHۂwJc[0^B."\b+E$'64v1)K Co *đ#$nѬ0eI|}l~ݒ %wO:7 KDf~JځtNr؁q?HDPmۆ9vfޅ6 +hmg{F+gmRp^zb2)~P5de3T>;W= ݚºJ@ejx4qK>EZ8>ϧǼ6')b9[qOYa"II9Åc9PLtF& fv%u~4MkUmSO6%#FU0R cZ;k8v+>`t(׼%ZFYЦa9*AL )CNzK>`アaU2bjFzHɇuPtDG LjHF3㰷dF6^#XO)p,6SP凈Q>kf}YY;g!y,_bs8 nhZA*l#02ĮLTrFoC@p6(J@8Je*ඵA< h7D8>GH­ 82Eg%,, ` x\\(ROAAՅ=)qfE+]t ^7Y#L.ĚSLG |QwEBf57DKI~ƪ"cLajb0 1D4jXkBY'i܈%C3RŹhŵU{}),(HqӼ;/ÿ)+ʁC`{ ~{^IQփ?SVժ5WU ӰNfPtar+H 8 h`pUajM˞w'EtRh4 *֔;,JLz2I2ptZaR2!JP~} $)95VB({=7N@)eǗ$!*S&|䀥1djC\Ύ8\I 0gza:zMLX "(U JW@e}I_%gH}g![^_Ca粆;I昄& \+˗*>D #n iF 2SnNTz92,׎ieȐ.d㍯E7-w8q$0B&lRBtʈ$\+\T{&# ~ +2?a{(%0lN<nTYHn~[r]/~pcUU&4瀆7M&O2L)G/xJ  B '=1G/Og*,m/ƈ,?xQ0fk". sKڮx Ԧ-`' Ww?W'k2'ڙ)5<-Fj':UG.ZQk" @?р8j/eXiƀnsNfH36\tOY/[ W=|`p ׌`tJUur֦[/wTeM~kM`buIb ]g2}!&]P-%n?k0g کF=B9a$n z* wώ&1{Ģ@9r+i,V4_"{>:&$ߙu=("'?<ٸ2ܴX= ۉ~=rCy .&q̈S7`?IЍfåk|[Wi06OΙZߧh~_NW":Խ(}kxkbv 9EuDMpw!N>bߠ7ÉSDM..uƳkkJ+k5Er 5fzWaZe[~s?7i*q]g%' BYD'Y0 ԦaP'n͔D:lN,dkWs:ݐ#5ipz6d횈l_W5 :͇cGH/^kt-lX,6jK?/~ХB'Mh# D)^Ve{%(dR:Hߓ`i[+5@<^|dñYUT|\ #ѭv]4,cu0cw611ig_xNq|'?S?XaTlv;ߌNۥOM2v"9Ca9u;#>wՍfQ [°o]].[|z: #yhӹ {B,{߅ k"u 0So/aA9ifˍc:u7 l cFY/ S|7ٜ'b}`3~JCpK>W ~x7ݒp{=TF̆:K,Za:J0ox@l/gkS߷&areOWU,3?>滫L_x2paE4kOVUHW H׳yo&:0M ef &^E,uZ51k9lp.%o 1v4$pT>Ӽfřl_ƄMИfLOv$ vb.V_ZljTuckPs@R],?'k|.uu@H\f4Ge@G9gnv ޥau" 4saKŎpv6ʨSq9hh`AlԥTd5y{@5^#{'ǁZ`B$iXt5iGnv%rgOCwH-B/3;Z(;K~!HBph[VϿUS{h0LJKDNORZ]M+n†dE[=]JWJ%gӗaCyGp'·0ȹ0b6'ʂ"H6 !-Ҕ>lB>@:Rm Ce\oP7QأSg- f]|GtHR=;0KoДE̠< WYO pjO$l!`E7/ɒŇ:0lr0zz}j2[[C\ŨُT* U-PI0%E< 2.FtVlVym4Qioi3Jh \ɼ-8J)-A%[Q&Z1w!*p<#}˾'Xk5^UglQVcojdD:FCjb9GZ41'}ݗ>= j'h?!*)%8 ʜs> gHm⃷ud#( BFC؞c%mG ~KףَҚ=8ܮ`RA0h 4B@фC-Ctc2FdZxѠl}A3FO3gťʲՄ\~GR0] SP[ iUafų^>lqo5lje_`ji{N_ja 50$ odQFZSp@cs&q“lzJ^WL4uة qqqwIƧ|kLrBddw!n"OL:?*G@LSC6Sd=$^r'H+[`LF SyxCjJk Tv {K0EΌ@r?Z̧̯|uGZ-MFݠ҅ۛ _ԵMU2㵾+"а|6 (Th&VcwuBf0B~VDYm\YB}?gcc#Q:qN[X1˸0e8-he/9 +!3ǮSgeVYC6* ?rJL8olgKمXou$?gZh܈0UcGdb$9MHLט!J&0Y0Ш leΉ27J#l<^Dz6|(v9SIOVM2 |FLDyc&?~-5W2@qG.uR@14V1][N'8B1(z45KJ NNY3f&SG me:aQ]AUP PJ4{if@z)~o˷qwR1Lw"K?#ಢ~&_C1OZ1A;UEZBDmZ:T?Ëj1-zq5[NkAa&.Uÿgǩ>?+ 3|7fzߊaBZhD;C03dXz`鐴VF:5)X!$Y,i.mPPG-aMxGjUKd)JIbGdNFK0AF7&WnDmV9k%o}[*rvfF^E^u묷|:&L)^~rӧ2>hf5+=BCR G[X9nN-H'zPш:sNC;S_-#H _ɡX|$~> T+XZv&G20=J bQY{8>Ud҇x?x9kΗ|?IEZj[Fx{!fJ(܊T)]P59Eʘt:'u{ٻE'鍫;GC㦙  -~z?."WYX"i3>VJQ?u|knelY'n &p押;93''ܜ+[#ydC.N/Ay#na㒗4$'[*EFv ( ?#i<0_V ԣ8䌰!mÌFO#KiBG>ϪU6/9_$k> nȒ)Լtr+@+r|^9/̈́}yiɫn:o(qw UZ~9TF;;&d /{_W!h9 "xi+q'uiʺG';ȚK_c}Y7#lSR~r663y/Y5/=>^jT"\@gw6!1I2Ǐb<%=C5M`%ӃzTJZ VW3}(-!INь 魡ڲ{rBk|(7ΤU[JR!%x)2J"vVke j{iDK-]ֲ** 1H-Iwю^V\#D0Gcfo {O+t 5EH]aHRnW/'Z Xj T7\gJacg(0>;Rj$AG:L`z?7r&~s'l3FΟoԍ`CwiZr#^RDpd^p((>dMؽe:Lnh"(EAx#MOtɚv%"DgRF. ci oCwZ ~Ű+QF% ܰITLr Ÿv>]:$lҜ'=%7EoiVқ[*œ9:aWTi2Q ľr{DS=нbvw$q׬*VzdMJ%R&z%s2CrBrq2"q n|1ʹz3 nKulh$]5};e$?OMRFT(f!}~&_Sx޾uƠ%==yZ>qđ EA8Œ}Sry>wېU([x}5e"Ӈv5[$>/ʲ&NDiy b| S~\ѷc؄01/ct0}s󜾖4nVc_dWB-%Ms'CQ&i欬+;PrZg?ҢttDAjnv To0!c3<k(CDzz`w[|jIUxvdf!4vX {)e28N/MEYЃlFN!E`ounn\ b}O &QQqV%o$p;k5lve͞L {ٗ˺(\Ґ.'A&31"pOɪl kۺhFEA؄@CUϙ⣛[] kψH.~ +X|H (iLtC6]f ݅jj:x{#k`7zG5d/?'M]ݝL]Ԛendstream endobj 327 0 obj << /Type /Font /Subtype /Type1 /Encoding 1127 0 R /FirstChar 11 /LastChar 123 /Widths 1128 0 R /BaseFont /PJFPYU+CMBX10 /FontDescriptor 325 0 R >> endobj 325 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /PJFPYU+CMBX10 /ItalicAngle 0 /StemV 114 /XHeight 444 /FontBBox [-301 -250 1164 946] /Flags 4 /CharSet (/ff/fi/fl/exclam/parenleft/parenright/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/equal/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/circumflex/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash) /FontFile 326 0 R >> endobj 1128 0 obj [671 639 639 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 350 0 0 0 0 0 0 447 447 0 894 319 383 319 575 575 575 575 575 575 575 575 575 575 575 319 0 0 894 0 0 0 869 818 831 882 756 724 904 900 436 594 901 692 1092 900 864 786 864 862 639 800 885 869 1189 869 869 703 0 0 0 575 0 0 559 639 511 639 527 351 575 639 319 351 607 319 958 639 575 639 607 474 454 447 639 607 831 607 607 511 575 ] endobj 1127 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl 14/.notdef 33/exclam 34/.notdef 40/parenleft/parenright 42/.notdef 43/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon 59/.notdef 61/equal 62/.notdef 65/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z 91/.notdef 94/circumflex 95/.notdef 97/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash 124/.notdef] >> endobj 323 0 obj << /Length1 1496 /Length2 8259 /Length3 532 /Length 9131 /Filter /FlateDecode >> stream xeT[֨Bqw.ť8E[X@`Ŋ[Pݡxq+P-PCis~뎛3\s>{5f|%m 5+@a\@n(@VMrb01ɺ`PG93Xݬ|(?HT:yZl% .f53 ^ xü@m+lɍ,m-`s#_FʎVP?–nNvqKXl%[aCpRY\ Q7sSff@``@!Ffvٺ*z-5ma6+3+8?c[GPV[[f0/+oft\l=xyyD_@\\̼0O@%p;Ba%H|VPn'c+7xݠ=A'3#lG$K:A\<6^N6`!Ax wH 1swDN7&xo nrʿ A7;&xƿIA7xË&xM67sk=c+KY V kp5?d¥  7V ­@p?5@o< \o+#p {BH%Z{ߧ"[ 0l0 Kn -ϟ,CaGnU )Qqf_3-O#F٦tlW8 pM}v7N{JipDt4s~(ee4?t WUNgu{COzBD7,N/Ź4쁗yy". cݍ6-'q=+$/썗cWoK"7rR c*_-f_AޥϰVu:}*xyF*Sx.mN6y9%Xcci], 3N5k:s~s!*Si\ckqv í5gBW&.cJ:ᝊoGwחwTϼ.~V( RެV\lya[H2A%Q3GFpkY&d7a9Ln .cL٧: EIfwJhH٫ V[y%.,n&gB~6'n %DCҭ'q`gfkC[D\y!sL,Tl+9k/_2U( &mmo`)M,}7)yXyxR*o:xTjѶ6XȚP%oDXTqgo1Gf)IQRtԎCXW|hd͘teľ >񴇲z(&\ƒ'A`B^f .8 []wn'N\S6z3kgt c:^ArR)Jq)}ӈA0{y[qtLq~-R4 D 4ܘD<<S5{_΋l%ކK4s>f7mD>(}#bOe܊Kp,p[kfєj2Q VVi ,9bm.T˕9ŝQrgh-OYHНG&ѕ:=rةWY(Uխ?gCz#]d*GSNCXp:1S%fU4hbÁ߹fZve5Y)^˗ɲ3t ˹JvzC9̈gN%1t{5ѽ @u?ODcLpNpNKP_Dpx MEw*螘IE?Ubmd% jWd [2ֿ&rNHq۳eQGGbC,)FKTEFM8Bd :ö+&8u S[1|M{z/}hW|B`6)g _H>M"fs6_Ȝ?(~hƦwX)|uVzwL ȩϷqMOA %|RG?FF3>됧|Q 8QgdqK?ddh8 .l||P2}w.0IaxH5b♸kH„y+–+;#y>m,A=qXX#L/|y?-nYPБAe!h% 1pܪAm=vl pN)jLW! 7_uZ`Ʈ ԣY[IpEwNkr1EF, vJ.egt_^t3z!E7}rUyb.EUBmΥ_B+rbL}?i .%B9[Pe9Sc!7qs,z-]H.8!nswהa_(d?Sq cg`]P (ut͆0X.S=9FuWB%09oKyڷSUзT ?vVMw{I:2 PhtAsO.w+]&q60G6IHzȂ0"ҐaƗЋ=-Qq6JyYӎDMX=910`P~ְg/WAj^Wǭ7N $N`3e Z.O_"ES= n(Z蝫JuB>`ZsaS{#F]u8ި"S0DžN7dM v׵bU9s*YT{ m)YXTcxNrQ-q6mW/!_I@myZ~f_?L->UzyA M f{sj^{M2Ճ>6{?!Eձ~"D_\_ӡ(A2]T%N<&SMdƐೖ '@N%J5NM{gQg(2_:pH_cIAҩ(|I1U_<AIoB@oIى|Irp&!d[t/CKv*H+y~)]]5H'a݂tAt3Mpo<z_M.nCCz7zon"|ͮ_a. 4T'Bf$,D~!TWC&A3":EԘ6ArG.[!>ݧ8aSu'.x?Аx׍S_W20%A1v#}9 C`3?NVL7}{ٺC &+}&HeUww9c}A|g=G_r.)0w#P57٘gy6lϱ#}řed88 y *bӂfpٶ؊cGcw?FLk3 #<‏*inY}( m 9lZ}(cGO;/vj銑13uEc' M[o PQlَdbMA5yYI5q Mr7/MOqH\7^ΐ_Y8[8qfxR ?ze&$\ވԴh W6cMS.oBd S8y[AV+XV"pK0J6v_Pޥtko4[Ger!&ęw]E SRvT$aV3]nM_L;#6S˩B2+1xS,b#~"ܭ [~ثciV=c=zs>歳R{| [J@ BJ=S^#Dc2)lQt2H$CIjSgۡCH?7I͟aT$GtS/6Nrf  nI|U`7ydil|y2 fID1F7z쬢k!r^EK5Ǯ z/޺ߏIcR^!>s`] {Z^ޣc mWCƇ,~15꺫!=$ʓK%lkn6ŝJg6W5Ivp፱`mpmE6;E.C=y$oMuvg2h;=/݅!g,Q&۴O+)Va8k4S!m_(Hpk(ڂ5cA妕 SǢwEhqJ/_Rʎ5&mXE P0T[}z+|#S2LdUs'V? XC}Оn{\O{=ǁ&߆דλ$K aCo>} >> endobj 322 0 obj << /Ascent 694 /CapHeight 686 /Descent -194 /FontName /EYCRRV+CMBX12 /ItalicAngle 0 /StemV 109 /XHeight 444 /FontBBox [-53 -251 1139 750] /Flags 4 /CharSet (/fl/quoteright/parenleft/parenright/plus/hyphen/period/slash/A/B/C/D/F/G/I/K/L/M/O/P/R/S/T/W/X/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/r/s/t/u/v/w/x/y) /FontFile 323 0 R >> endobj 1130 0 obj [625 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 312 437 437 0 875 0 375 312 562 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 850 800 812 862 0 707 884 0 419 0 881 676 1067 0 845 769 0 839 625 782 0 0 1162 850 0 0 0 0 0 0 0 312 547 625 500 625 513 344 562 625 312 344 594 312 937 625 562 625 0 459 444 437 625 594 812 594 594 ] endobj 1129 0 obj << /Type /Encoding /Differences [ 0 /.notdef 13/fl 14/.notdef 39/quoteright/parenleft/parenright 42/.notdef 43/plus 44/.notdef 45/hyphen/period/slash 48/.notdef 65/A/B/C/D 69/.notdef 70/F/G 72/.notdef 73/I 74/.notdef 75/K/L/M 78/.notdef 79/O/P 81/.notdef 82/R/S/T 85/.notdef 87/W/X 89/.notdef 96/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w/x/y 122/.notdef] >> endobj 320 0 obj << /Length1 771 /Length2 1151 /Length3 532 /Length 1712 /Filter /FlateDecode >> stream xRkPSLyj F<51 ĜrJr=@">*cyRaJ- /*kUlݹ{[^^4HCaP %&GR 3MтqXA  `!>`N/- 8&W0}"-#J B kJ0%&i4`čtN bR8!JlSš$AU࿁!]TפL: EB1VQX1Lj'dM-hV+'K^E46MG8bS1qRBtکY J^GC= E"R T M:<(4U ߤ<\.xHQ4`OƜ?b$уx6Dr=%Ni&F) W(9A!X`=D1Hg ), >21{{_鍌e\V往cg8C6V!0 L㽧U+;oi;ُ9r o! W#ǜ#bA*^/(bv;[d3(]*mmyO{`]?z>qξv=:\0捗sR7Z<)WSxe~VY.Mr+Y`*]7ŦU}ԅJp|k23y!ef']a~K]#wEY=OVEZ5k uk\R:E=c/i.1I=^Fb}fxyTY</VF Vp=Ƒ<\=voٿ뼿nNmq*|ٴߓ|&!5-gbAs=\v% DN.}},؂cB]/(4 Yc?y^NF_E$:|kNXd/X7XuD6`֞ODߩJBPRz+mGSad&xсc R^u^{ʸkG7/ؾ"tPğ2sp7[ѻGͷEty~8Z{?+0Ϊ(#[]`7N*5n4mR"n~+yZLB ڡ'*嬜'}GϹ_25lDBت۶]s.wr6gGb.XI~׎Ն q13|/{mvͶ4WҠl3PQ\D)[o%m^9$?a;:sv~ӌ;6hIuy򳡼Yz.,TPRBqՁg߽c2qsAui߲"͖ݴNMcUInj9j,俫Iu Uɥn_ 9!]aͫ2!p3⸺5+* 꼾sXT~4'4ZVOo7 h/͸OI7'^|d k"XP+xsdFʫDVU੔@endstream endobj 321 0 obj << /Type /Font /Subtype /Type1 /Encoding 1131 0 R /FirstChar 60 /LastChar 62 /Widths 1132 0 R /BaseFont /VHVVXI+CMMI10 /FontDescriptor 319 0 R >> endobj 319 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /VHVVXI+CMMI10 /ItalicAngle -14.04 /StemV 72 /XHeight 431 /FontBBox [-32 -250 1048 750] /Flags 4 /CharSet (/less/greater) /FontFile 320 0 R >> endobj 1132 0 obj [778 0 778 ] endobj 1131 0 obj << /Type /Encoding /Differences [ 0 /.notdef 60/less 61/.notdef 62/greater 63/.notdef] >> endobj 1133 0 obj << /Length 155 /Filter /FlateDecode >> stream x313R0P0U0S01CB.cI$r9yr\`W4K)YKE!P E ?0? J!DH" @ l%r38 H.WO@.Eendstream endobj 1134 0 obj << /Length 466 /Filter /FlateDecode >> stream xڽN0/`yT )@ `b@LCERބkf_f4*{nx/=Jb ZEIgsXs9$r|vxM'Y5%* J)?$Mϭ,\濬 Y/d}ɺ۪GY~e]zߺ y\[endstream endobj 314 0 obj << /Type /Font /Subtype /Type3 /Name /F31 /FontMatrix [0.011 0 0 0.011 0 0] /FontBBox [ 5 -25 96 70 ] /Resources << /ProcSet [ /PDF /ImageB ] >> /FirstChar 136 /LastChar 169 /Widths 1135 0 R /Encoding 1136 0 R /CharProcs 1137 0 R >> endobj 1135 0 obj [45.2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 100.4 ] endobj 1136 0 obj << /Type /Encoding /Differences [136/a136 137/.notdef 169/a169] >> endobj 1137 0 obj << /a136 1133 0 R /a169 1134 0 R >> endobj 312 0 obj << /Length1 1291 /Length2 6916 /Length3 532 /Length 7704 /Filter /FlateDecode >> stream xe\TmI i %nCdn%%D@SDB:%>|u3zk 5tA?>+;鈀+@< eEYW?wG{O<_I"Yh@<0T  @aȺt {CmA 'j%CDr7%@IrPjDzAQ&?&Wߖ!0GzyB[;?SrӀ:zsUh# wrPrj;z8 .пPJPC]]V^_6OտfoFM`B%2^p#u ww>dH pB}P_0D@ C(-_,::@C+jC" ៈ(hpAM#P I TD@$&oBM*Z(Ato! efP5m!?J? z?%,\@7P?Q vDix( ?P}~x^!jG_y6^P߿$wlzàP_ F"e}dybH6d_[!Vbo:Cn _DD_\G&m¹s>#ExFY͢Qgi-<ةĂ]Ez]r<i !MP!C0/,fb?#ͩɤ=xcbWNAqr1̴עwEf1pKů_nڋ%aT4hp!M2!if@/J`QfIƮ4M"GS"CGy'9~GUF F a)s&;k&W~lު)#v8⣒Hp kUEw﫹{^`PS]oJ'Kۏ=#x ωްphz-]sA5ޟ7p! n'rkAC 7D 옪]fבԒ{uV`nUW^}0#;cj%"BnAC톇|y>ڝ4eґ'NjA %16Y/b8Ll_ fr 3j=w8IqMC(R ((Oڔ% F{ 14x=y)J^ ML `tQ¼vww+yՒKŴK?]Rⷮ HnKX>I`A$e ٜaZ >i*4P~<_)%3LGICA!Tw9\;WEvGs i2&36]F|2z#)dxY6V*I=ƵkQֳuf{tF9J0g݃eeů /A+cՄ*h7>WH栀7U!ru]t޵(+Ss~@;ɗa~ED3V[F㱩Q,SodhmcبiA-m@yھ'Q&$vκ~8SIv*3('(pE)+s80>|U`[ڳhG[߰hY'#O-5ik-:EMI9j;rɣ "L~b`nGc'eKre̴IAaiZ|S<6 q-Y!&9[ 5])4H>-bR>=?&,h x|>$ٲE4,G(?ai=v[V6<)AA c1[n G# h+jm^β7j%1͚i?W݇u`t.+5`bހETl$ulz}X݆"9[2+y>z)awZ'0^ٔ=}Yr_ =%ew ذ9zF:q6K˥*1Y_V1-Vڵ!xޡSsG<ayoWa^KQwtE{)ڑ2$K|N%]\ϡV^"5dbHx-T#Q&п \DtkB;/<>{Bk-|@FZPy~MΆ'{ PFQ{I)RV[I9@{v؞8?8)mmt/u &rE}4WUARGyIs#2ec|$Xrf :-ᤎ.}9nհ+bSalїS}G r<Ucu6ө2Y&⡲ CN[o>Iw_[+b9Xl1?`G^gc \ZU JT5D]*O8#7`?TNm8 y'VL1T%j ol[詔Ls//CּjoIF oJC)|B ^:[Ag=z^ ն{oai՝ ڱl?nx{A*dULA4SG97a ^ǑQ)_v!"Bl+*tئkf Ƌ$A{&5F|8?#<9Uw. K=ʫgiXCh^~QKڷ1D2ON6ο _{g*7 YKh)B:R"kQudg>Ҍ(E:ݪd  4+ǶD^0uv9ݹE*uf;j2YZõ *_C;gߗ +@){I SaG|\+Vʹn-Zp0Ywh>&-6#GB=,ZJ;+mB1jhd\QO/sYi%ۆTsc4&Ռ쳤 mzO?<5w}!^ t"^{Ct*@JC˄ zbÆDsP흤uc[^+˅%zTH^6)@cQ<"1-oiŤ-?Ws͕N~Ք&t˯1/jjSsM/~2m-$5Ume58IBY퐏d+Q mL;Z uVwO+eFckݷY46U;jO#U4wJ2r wW-qSi,A]61Y_9\,R0OűN O%*b.LPrH`DyNw EDMLyM^6m?dm39ONgnDdޏP_mM֒ ];]HF+۞^Bzxev8EM .F}|3[fS, "jɾBޔK`^V0= VDj3bAgK'uFHU[K|{E7G?`+ AI\Lɫ:o#Ds_:SxEbP .nl1e29Kk]r9}wnĶt%kIpө}gcaO8j7ԢnD>)炍rR/r~|#̖v g`Ǣw%<im`D*GnD.EGCgTQ~ F{Re+n#'MD_'n:w@t~䏘HިIڰtHB ژ :>5Ϩ~ˡ=(OBw=eu#h"x>K PFk<|Q~'b&-$U<էF\xԥ)}8[Q%UBI,LqϠ9'&|n\ݙ^yzn9$w,7wk^{.` Y}_3x~> $V;vjuK'Rpd4ogWzixF4.jbuEMɮ{4/̉Kpx. 2'ܹ[@ډ`L ͢)ǍNkA,C-F&;dc.[OޮMLLܟ* Y,XH9ƩZYr>[(h1)蹡: ĔWgl#X`x 8aSaG6DJ?fnur =󦆅(̷ )g]a6®lc(\|Z!#'}\w\!:u"q}7!-?eIH*~rCvv1MV A!V2iםLDe5Fiጵ:i/K}ֽeT5.&%qTLdǝFTD9s!z*<|^Dnʘwk;_/cMEȅ?!Gb)ZtUHwzGJF )N4o돬FRhk٨o$>%F+gh)0.[bE׌G/]%EZ=d;u`'70,1:RQ%jOj%?_u^X\+AzB&Ff܀yHKOQF<…$iշ[zSW- h2ݲFѵzZ-,ą^9Hװ sh"2q/PnΎ0mB'cH2>d} Wc+S?7ճ: }Ƶ8T fr3L*I, Ϲ4ן$q~5EΧĔs *-Ƃ%cuYKjS͸Y$I{r%2յ}sȗ?Iuk)wL|XD97hr~-%UA u|uF)ѕr lƢ7<|eGnr0oV5B)U^|^3; 8n jf[Fl IF>ֻv6 D ?);Vl{ݛkeaّ+yXY\09K;_E@S"! 1P-Ov~԰.lsՒ<DYNwOW(m)j;ͬ^u@|H٪yV\ > endobj 311 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /MLLACF+CMR12 /ItalicAngle 0 /StemV 65 /XHeight 431 /FontBBox [-34 -251 988 750] /Flags 4 /CharSet (/fi/hyphen/period/slash/colon/C/D/E/F/I/K/M/O/R/S/T/a/b/c/d/e/f/g/h/i/k/l/m/n/o/p/r/s/t/u/v/w/y) /FontFile 312 0 R >> endobj 1139 0 obj [544 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 326 272 490 0 0 0 0 0 0 0 0 0 0 272 0 0 0 0 0 0 0 0 707 748 666 639 0 0 353 0 761 0 897 0 762 0 0 721 544 707 0 0 0 0 0 0 0 0 0 0 0 0 490 544 435 544 435 299 490 544 272 0 517 272 816 544 490 544 0 381 386 381 544 517 707 0 517 ] endobj 1138 0 obj << /Type /Encoding /Differences [ 0 /.notdef 12/fi 13/.notdef 45/hyphen/period/slash 48/.notdef 58/colon 59/.notdef 67/C/D/E/F 71/.notdef 73/I 74/.notdef 75/K 76/.notdef 77/M 78/.notdef 79/O 80/.notdef 82/R/S/T 85/.notdef 97/a/b/c/d/e/f/g/h/i 106/.notdef 107/k/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w 120/.notdef 121/y 122/.notdef] >> endobj 308 0 obj << /Length1 2282 /Length2 17124 /Length3 532 /Length 18395 /Filter /FlateDecode >> stream xڬeT\]p!8!8P{p !Hpww|tI7:-gU&WQc3s0H;ػ21I(1#PSK8]%]dl||dЋLҕN$21;=%TؖL L&fkK.dԕ`ae򏒬Ͽf@r8IO4s$3#(9Kmm)B?vV`t8):on3+u52;d"m0Sr5$37u+7' q T]=S1gVANKނtz@EFfeo xY\Aė 9bFvZAA sAm@)N@W?#\d,@;0#`W*/(b ZDd0vO$gO ?A4m.I:-=-9%nǐ4[c?LI8\ {W?\ oWKg_lOMr+:.a /W`BpTgζ]O;rN@?}ӦJ3'5 rC O?rC A?VQeH9!!(!(xA.*\TE\E\4E\E? >?Op~py$Mv涀?G wg$h@: +hN_ Av!/-_flB_d5_r AV?/Y9<!/YB_r7<)򂃩@ujcXԷ MJusK EN ڿ20QH_ ]"}>MH_:ŧ|;p3:j!ԾPwx >Emk;W+M)Ⱦg̸z ./M;ݴCuKP䬤0 J4B͙zNuT683*ۋ@p wR*BCK6ojn=CFCBWchNȾ>'Sm\&hB#XSddNcyei!P8${E3|\v~Yӿ)  4(:Ċ^oz2WmE+*CtQc;@nW5&{Lrb 0!yk9 T”(I¸3dP Wz{ (ةm1I5-Nְʴk\ A sw]宊3!rb _|uDZ$K;\iu?Kg {o @]ކTJ<'lջ֓񯲱IQhc"p-,o,0.t}x!RH['`{K`,jv45VCvz6.ڬ-GT}ֳ2 2|3' rg]v?7~p}35$:b$h7MdeW>V,!GNKۭYvkD"[W5]3Bu*1rEpZ }*cϒiGe6Fи6-J3UB^f:_e :YRŪ" {ds&',9D]I?>UKdj3!:(,n)0]`ysY[O6(p"zdK.1Rw7ƐOK7"3}Tmo˃>Y\J1}eq9b_(s~=A1hU<|_h틃49qOв ./\ڐ{m'r'qOcl4Av3-:m^bȎ6ꤊ,;bU-9Wڎu2]*>-8D+Fq+[1`Q= '=ǜѝɜuх).vb!}S+aSO#CK/.ث1`<%r'F?lIb sU'9 Axk1~Ư["i*[vR+uݨd;zd'*:#ועk)e *~`򓺋R-[jRduS;;z.i8_l̆_siV$y\CbJ~N"Ǝ ܅AŁ i}Ǟ!Q#֥Ēi_ ZAg:WNf~IɌ %"lcOa6[<^Wr vxنmB$m~A?"] 9`:?")v7#Rn <4Bbf+`o,zRVJ5sLw>Ս)}Pb[u=t#G$eh բQ[z`D35M\fVkH?cs./AM3@"R3T$EISEE"*(#D*9`)WwQH&:N[F J/< 33MX8ͻ #=#;w:sxwy>6)1(&S$ 6E%Ԏ ^ /]-p3D_V/8}PiܥjXX\ Ve&.`A6x9?10PoT! OS%2:gA$&\a$%"eчF ܍Z{] 7;{3@-ġshX"ҙ~9ɥ<&E'h t-= ;5CgN )G|E j)Oߕi ΏQw _ 'o <-{9o[j2ҟ}Mըs>s)&S ʹ(4i(p jzo݉uNF'M-{3DO^u5=ĉޘ[^×PJo'R{j`Ip0 b`'ᝨi77dU#>LZ nh&Tf)y޶s7}8[&ry=]c|Ƥz*3s֗~(~Y! 2e)`*ާQ ~n|kƻxg&Ż1(I_=SBtl ǔފKNs R&rFMǣq6}5YTQ}d&%̸ZnT׃]XI؍Ӽwज़#vCi汗:n8ք<9;yNXi"PB@UYdlrr=|ЊY;0 P7*G/)ۢb?S @C^u:gX]~.˽R-Cf`IC1OY)?gΞӴtn|EP ,8`@ᗲIK>$a)% Q̬}tc*X&bNEjRKf5uOc8P *gbW=6͐!HYz7x 3J |,I ԗ.)s]v萁0W|ŜS~qOS7SI쨭o/Vcb1"o?9:QGB<ՌҩqխV}k8CF~g֜e6\_/'uXmlx* bҠ -HÖcY-`i1JKoمxV:JG:aآ%j[4jK%ܗfI/b1KL`>IV`o)+ͲB9d'Y֕JY+ЏuI1]e >yMJއd)`B>k7wpz}P!J%ߒ/G䭉١8E@_3Gݙdppw3tji(D[l?ߡEIڜگ';P3y#I9uG?mi5u“okֆtnhb tF'[>H>[RuL󴵊Η>& (9ōՀezUx[#aZχ!0gA~.I'"G_e ~7 (BЖ~]'#=4PxhNۭ_>9}bY%MI-R2gçE.8\9i`%nɊT* H[&k[D) 87^Je ~`A6i7`S x$r }wF'!w5T 3k8̑RĎ^aM2"4qc~Fvn{u=_T,Bl3 7܃>a?bymunt7X4#戀dt[ߌop%M:" D >ZKodHl.B8l*o\G: 6T{B15'd['хtx)_S̬ ,sV`Zx̸([i Bi#4r7"W+ +ewǯc1/sQR#[fU;n mN 3T1n4 )c,lPNX|:-?b]n:!8ha8d#4e4cNjȝWɊnߣLM;О^ ͫ3P K 9E{ZʮkN丣 s0i$J/H†~<%*/lMh\ tQ)ZoG;ď&jQB)*,Yn[Qsi)/:SjȷGHxuq}ƗpxODC?>p%@}8 )kW]8bs!mUG*U~>ܗDYC= q'D[Yْz ݅ђ{>*R*S{TvHǚNHC &11h9˽љNA;\E}lN3ؿ0 g > &v[3h^D~)%@AjyJU%U8tJ&Zsjs+: 8s?X+`28>Pyq"+MP`=ٷ{UN#W".ܒGP(ǂMnp}f +yіlL J92xc\XϤq-ŴV2:d;v+.ј1`c Kh1ũf4bB "n/Tuj?>>=!&lr_A@^o4ud]QDSh;NGR+}uPL~a œJq XB62u7/oZ1T舎='t3x IP+z|gg> UNֶ( Q1 U؄M )`j¢ Iz&a{Y9h~pLmzː:%)0|ծ5ZsޏnrP.@'gqVWyJ}寧uIˊ;,OޤΎaKԱ+[rXWCO#y؈#bȠ̿!z;9Q?a}ͧT~4gϽZ.<7S]a$IӁ-_-$Ψw@![^>` Pe [#y!yƪh]53 .sMBD^X U93:r#ɱQ/@ՊCW] nx[V`gӆ dw=/|'z2A̼euwC"]WR?-^4~F }VA^ pb~yL+AL8g7?0Fk5 ns hQvnةc=Gh5Pkl=槍G'ׅv5ѷ&c#lרFO\p iְZlɮV~@I+xgD<[cUM+!A}rdu8I ED3ӎ9$Y mW `0SJ kaue/h{09Ӷar oނ $EA knT`uh-r|]dGt*U$?r1W_M`R\ǫEsbtdNdѳE}G̜1`?RաM}-lvob wvBR S4n 35yK_Xj@T:ofLt&~6ghtwS,B( dj "8L\?8ʈ`thE ݢwl&ؤ=ɭU:Y_XzGhN E*YOMq7l $Bt >U^p47D4Zp6lḺ5DVWIԹ4 KܫaT"`2_٢:|d$iQJ8H {HrzrGI{ ZS`Kbl^CNdAftS; "&=d6Tb꘲W~n /6R ot9Iٳne(LUERBypCyHjvYBOꯋP׀ (wQw|q)؎7; L ù[OH Ry"c,|cY8(nkvMBҫ5'%Dd;0}NFԖac (ҝTd^~ bgٜƠ~2eBq\u{_&x>]˙l!{S#kWL^yV(5$mQ+bmd1NEFB(.ԭ ᡐ_S<Ǿ;C:6ViΦmrWX[_JLnʓ0O{\eޏ\s~׏*^oyRDFl|;NlU]J YбȲ`e vhC$'%LC9R= Z[|N@ɭ_I+0ps _< ?1=` ˝G:> 6fɖW/>QWC[Mao"\+&`+#8go*tw*΂"1QӄxdNq$s͚_5p'8PHS\-j*S궉G+ܦ^I5g}"=9[4pxt_n=n!am'w}EFC3t0{wh89\o_ B H.TwVpږzJ ͡i -~0CC:-Q^Xv *JFyFq\ކ'48.Z^Y*g]T YOksכ!C=^kɴUl{P)ƽ9#HJIj"}W}z UVw۞˱L*?EFAl@r vBN~ftzw>q [~U%=:&)80:Y>-toUc]k~'Fڣ, e12&骈Ooֲ܆ ߉혛D%&.ȭQ<u&uelN@5K~KӺ#Wb?/: ^|j oZ9m Z~j rkcI6~1!t{z1%O:p2QqEح1 I4 ʮ['JCoqQ oޢwj8v/|cЛպl(C j4[4(_ }hGv&߃;/ou|6. et'aR3)%Iz]wJ`n&A*94]momz*A>V+*n~XSiscȧ!ΣwřFrLQ>EiW&UR $2BnySSwInIЌcY#u@\3KpBIr(JR~>K|^`y.?sh|Oc_g(hz"$~+ OnmiFV8WMC^fiqJrd/g]Lj^-%Goy=!:g*຅={uT,W%@0; k V,4|z2䴴,2m`-dga{#@"w:ӀQ>zנ[Z ͘нTk:9иmn61ɡ kX`8j[`\phƍ Dbxc;cs[X|QQ>g0!.°lFBȋ/ZO++}T$MϮb@=ݻ )IYVLW΍|i%t`Dydfq7ބu2l'U{¯A31gGDR=dGԪ` _&w~z^Yie2:ы;w6 #tw`y{]HgHTrf$hC5.:;Jh|1NL0Uv2/9O^s3BԭfncEa~U9̭}".P_s~Idxi^sBҪԮJjfGkU ?A#LuM,5Hչ&w@ lx=@$_jK*@kCI)2icȫH/nǜ[h7?"!'fգ/*9Y|یW^Xy=UE=BFkOu}m0n+x7RGٿw \=cYN1[YJAJIL֑ANJD}t-ϱ%03{P{4s,r!}HFGXȄBS2CaIRۤtahNf>̈lE3w >?+n 𮇘ERr=4lb8g΄k^(ș.Ju'wSDs,9LT@XA$Mv:`ʈĔ& u{,Dto`v{Ϫy=ݍ6zRWڹJ8sͣ^[5ziH} OS`>ی9?zppد#wHNJ˷o q+4=\=vm<?C Hogs񫤈yNxNf-Ama= LҦ`+~2 cN>meއT_h"/zq}{DK}Z #+i>ޡ`==n Ǖқzmo[gE\]d(LRbۚ3؆1=4{0wwA-ȇ *&3l*# J֫oEf]5ڊk0[I45V;? j8%Lt^̉] uZ|"I PbV\*qwݱ'I*^ w.2IHWxJX+piv=o=)Sjڈ Yq63 f9=Gu_񉖞HF}V/dk1e_pz 8\p·ip3?+G^כ2¶} \WL-VlKe9I4nMJ۵R`w1_LzC̢O"89JO:KdD[=͎Ծ#3 %"ȟ!~CԄ"[A1^ {nB'SlqʶjA'%}x@\_~|Tph]ovE =y[Ӵa?{o!;s~P8h+N5Mr0ڎuGU3Q<N[|n ex?cmyI˚RX})aUJGT6axUHu5pgtw +Xojcw1= dw"8RٛZIJ$Pg< Cs002X1h!w8ZIQqg^a]c0Ḇ hLI֦=̩1a-sj*4%Z+^L v:]X{X1soVՖ|Eiܗ),^gxԌicP/ -.0R2g"}ѶZ,+77خQS5ɳ T7{o`"@<(%PfJߊ*l4}ǩ1*qN}  R) &mmZʆFĔ*A[R \lVJK4uF}ZfLZ CRs?~aơ|^|h6L@_ =V;uZr3G5G=fOv!Ia:cN;ڙ&âPemۊVG30 f)/]͢ج8Z228j.Goy7;|ّGR?`Ԑԯz>'v馽Vyn"XP}6Ȑ%h-pѽG'r_IPyI,ˎTp.6]E5Jz` tA}}}*''?0w_|Ql*j(>tt%A*<,/(51K\:D[_@ni=gSFv<]lVp6rVg3 o2o w"",fZT.23Rxs%0'R|L+  oqprn$dgU,?Rևa'׷{]b; Qw }35X_2Sis졶mqErr Әd}'0,ѳhX2]dZsKR)qj;&x:y8l> vE ~Wj[3+tpLW/!l-yp2x.pŗWgti~97B_Vgc{@Lggl*%꟨/^yM?ŗI662 Jg;:Tەy?zfw9W0ohU"XHIbw&~3.DJ?㎸]oפ{?]RMO}#y ,]n T _:}M@H~J9+ҝ_ j_֗mЌZZnLx}Z*1$Dx ]ڧG/ &EwL@S<6?}\{Òh=ӅB c@O3Ӷ'+F/X$~{]|rs4Z< v;ѣJ@wԴ$+0vATB-T_VVh@)NM._p2ISj!PdjUJop_R`!-䚲+> endobj 307 0 obj << /Ascent 694 /CapHeight 683 /Descent -194 /FontName /FQLCBU+CMR10 /ItalicAngle 0 /StemV 69 /XHeight 431 /FontBBox [-251 -250 1009 969] /Flags 4 /CharSet (/ff/fi/fl/ffi/exclam/quotedblright/numbersign/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/bracketleft/quotedblleft/bracketright/circumflex/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash/tilde) /FontFile 308 0 R >> endobj 1141 0 obj [583 556 556 833 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 278 500 833 0 833 778 278 389 389 500 778 278 333 278 500 500 500 500 500 500 500 500 500 500 500 278 278 0 778 472 472 778 750 708 722 764 681 653 785 750 361 514 778 625 917 750 778 681 778 736 556 722 750 750 1028 750 750 0 278 500 278 500 0 278 500 556 444 556 444 306 500 556 278 306 528 278 833 556 500 556 528 392 394 389 556 528 722 528 528 444 500 1000 0 500 ] endobj 1140 0 obj << /Type /Encoding /Differences [ 0 /.notdef 11/ff/fi/fl/ffi 15/.notdef 33/exclam/quotedblright/numbersign 36/.notdef 37/percent/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon/semicolon 60/.notdef 61/equal/questiondown/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y 90/.notdef 91/bracketleft/quotedblleft/bracketright/circumflex 95/.notdef 96/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/endash/emdash 125/.notdef 126/tilde 127/.notdef] >> endobj 305 0 obj << /Length1 1344 /Length2 7292 /Length3 532 /Length 8103 /Filter /FlateDecode >> stream xU\\˶w4] .! 8A A-+^PH_DO sʱ$ qB,`U w;#dpdP_3Z`7'ؚXC`[ /C @_aky]plEk'` QskNP_jp@}O;d vg>_T[@!V20[(M ր[l,n`o 'AY`oan;| ޓ+_ @ptzx-~Gv`?!AN#B$$ MH 5G7T܏oC"p=WM&oC%p=׳pA?B7`p ?B@oua \oun \/6~#\owDVۏ' ,aр+ shfZ`+NVӚ"K 'Pem?&wMc%"B)3)$DݤrmU< qIHy4m28Tp~zi|_Q}piaQ_q^"=BgCp!aLnTD3?~Ki@Ԓ~[@(f6›B34Ӽ|L"*ZXJXS[q/N<8}i`5b{ w ᔒVj+wH]T~ċ\XbO ǭ2XLzMhʄ'#,r%_Xrw~MvNzk5EJ޲򸏨 XkܹBȿbDbF)3P(D;%=:UCQ!2|- s?E>&NbBKsG"2ndƀaN"ٸ{I𞅢JFr֩泈p ^==ԛ4sEςvl"B*K ~oAɽQ@ΟYkXox8<+7Ouf'pkϐ1h~6&(,p?`*бw)[R !L dj%.VV{̟!2ӽ;8gu߬v/R+.:71$Q[4/zҮޫ`"iQ/+ ķQђv4bX`QwMAKѠJAye-"XBQTE#JSw_=hx,[Ѹ?ʩuzv^{$vdѵTYjeEePBsgFhDyOg/>> m>7E:8=:`{VWhH+:=AwZpj"(M c.bSEXWCC⍃cxU&5ч{ Zx΂vISy.,4NfլVfBdd|()Yj:!ϻ&b`~e3A̚S/i};"۸z&ŷNwgGBo !*`Y<{[|FS߫н<5@6dAy9}zG1[= _&kN1n[nsr8{)Q(w!lM$H-q2jq;)pO.} F[|V8 6=t᠋$m׌z%{la!u>O>@.~ቕ@ ''FHǒBz+6W8CK˚4t.DNN1 (H4BVڡx7Uf[ыhNG*죬aΧ%Oyg" ax.܌(531m›6$)7~|xydaE^|$]h_fW-iQ,'dm% /ñ \$-VLǷR'%썟,7<ȡNjNP&O|Km, rC^2e&J~>=Qx1!gF: l>rDʎ;7#篗wxqvFHvP\tZVT? } +k~+">>ֿ |FC\<9x΃f|'59}m\iYxRg>N JHV! S҉E!7{I!W+[/=*lw#Ô~Κm7)?U7igeJza7~""C(gʈuBܑG- 'qBV>&<ˡeb>^z %M;oM `LH璂DGYRmh6}tc֊̫QWķI[nP0J)>I\ØJ ;TݿuBr6)D0z^SJ^e mQZYMb(JdJBhI/z)0It5214t@`-D_q>؀xS/I5EƗ3&"jJr dKϚe6fSeͼ Pԅ^l6礂ďH POm/C62ӞmmM{^A:ym&QD.[+\~ rb&= K).9 e(!].} p!ͼQltQW=v F"j=4gٜƺM7KғC'eh%כd:5g *{+Ruނn3.D񊵩aqmf .ݬwkZWZ uƫ#=)IAΓ~NF&g,¦2+lӄ_ro$; `6NmG8kݓch|0_&y%Vz:7N4/d7uuȵfu:"z 6vu1Z>㻓gQ#Zc*wv\S2GZ<o]Ƴa/< ˮ|UvZӗ& xbq&Ryvڵ$$x\qAu߈"h ^ݫ5т臱y0Z9Ї7"/̫9nn n*ŭи=VTҫӜ\y%b>ixټ~C#JE=@^gDe(c‰싀N7*ZZ7 !{o}wH.!h͕D?6CQ7FZvx텐A>4lmI{ce✿hIDA!p<]"=%LV0#!@Akf&*VǸt!S&-w_iWg/v)~=+ SxL^&I#c^}qzxa(d^7+#DY-5}''o#o*~.Կh li e 2W}ްSQ V5ހ+?c,ߌQH_j*OߏFmHf0 S[*J? IzSM;1fѫ\52IˌN`2v/߀9dhaAVGgloכ՝" '<[>۝^8B9 *MiQlC_rnbkq4Mbpga bgSJ@ã Zww.8 a9ѧ.TDQ&޾59Oq3,_sMa.:m$WT&jU娃=)dgA;{nlGXZLWDIS_7~Vy'U6۠ޜe w;AaYj̢{g=+1WƄoЕςi29;Iy}j*C~Vڱk13fS\ʾ_|rJ#QCuh8Rޥh'%iyɘJ8G`m2M%)k*g`MX^wyÞ-dN FVQŊGJt._JB$M/k9O @,tH 4pq]xf KVW_6 ]6 U nq { Su 1F5wSJtnڥe/- 2H8gC[=GP%t/n i1b/՟L" LQ Sx6wtǛ5?4gG=:ƅf67<,w|>I8 Tv=jq]RG JĐ{G``~N¼\ppEeW.{(soVp. )H'6ZYQv`#$0=/*&A% KĀԐ~q,rVwqbx:CB49ɵe\@DcCFR3n,f R Oֹ܍ =zD x*ꊗq lnd,콞DnC_IEM{L+>Q=%Oѩs^1(Ѩ0g~ypK)@lki ʶ;ti&S?nE`|μ4K8ށlHu|6~fD ;Su, 2WVeuFyiZ9! Jc59ѶcGE {I) SYHrf1㛑O}㦴~iwQ@ B4 /_ J=Va9`F^%8\T9l߽aM֒Ui:D\虞l3_d(dВt3ɪl[ڴ6tk$.DTϟ "I@69_0f0mr$./k㷐'ъJhyuJ/O|\dv#wq+c X`HV_YQFLXP̾WY-XyW5_#tlOV]~}p!_=50+]$q#u۪Ml L;˂Jj Y>N󻛩 /1^Rn" 90=+DsJl5eN+t~%sVG[SG$ 21xɫu0o;~8YM.6oSe{u}k-N_zJH;R>K+ TmՖ$;k=U(I]a}n Dz"owpy%)'aU&.܅@a-P|АV *PJ );_Li: #j V kb!57)4+Nty@ lިTFFLɴI5'u3G[7=%D^(on Ai,[['Bs⻠_ל Ɲ-NO @X4qWc#("|v[꒲nBo3, m<=gy`)-*GPHYgךE~w_?UR Um[͋ʤ2'eݱ*h4G{\~zeG黸GFXZ*2vPlu>m GBr^; uC: \qbUs[AQ;3QHupKn}FS}DvY yaa`)ۦF'$rֶ10}{r٦)IF5OeTUCZRG[quՇc-{ ŢudL'QI}A#gk ܰPW8I sB21Σ45yE.Sa҆-,^Vc֮zEB ѠS=zAh÷_kߓ1:t+,G6 8H0J$KP`gwH3NLJLѬʋ`o` Ww'G W9@}endstream endobj 306 0 obj << /Type /Font /Subtype /Type1 /Encoding 1142 0 R /FirstChar 13 /LastChar 121 /Widths 1143 0 R /BaseFont /NUTCAM+CMR17 /FontDescriptor 304 0 R >> endobj 304 0 obj << /Ascent 694 /CapHeight 683 /Descent -195 /FontName /NUTCAM+CMR17 /ItalicAngle 0 /StemV 53 /XHeight 430 /FontBBox [-33 -250 945 749] /Flags 4 /CharSet (/fl/plus/comma/hyphen/colon/A/C/E/F/G/I/K/L/M/N/O/P/S/T/U/V/a/b/c/d/e/g/h/i/j/l/m/n/o/p/r/s/t/u/v/w/y) /FontFile 305 0 R >> endobj 1143 0 obj [499 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 720 250 302 0 0 0 0 0 0 0 0 0 0 0 0 250 0 0 0 0 0 0 693 0 668 0 628 602 726 0 328 0 719 576 850 693 720 628 0 0 511 668 693 693 0 0 0 0 0 0 0 0 0 0 459 511 406 511 406 0 459 511 250 276 0 250 772 511 459 511 0 354 359 354 511 485 668 0 485 ] endobj 1142 0 obj << /Type /Encoding /Differences [ 0 /.notdef 13/fl 14/.notdef 43/plus/comma/hyphen 46/.notdef 58/colon 59/.notdef 65/A 66/.notdef 67/C 68/.notdef 69/E/F/G 72/.notdef 73/I 74/.notdef 75/K/L/M/N/O/P 81/.notdef 83/S/T/U/V 87/.notdef 97/a/b/c/d/e 102/.notdef 103/g/h/i/j 107/.notdef 108/l/m/n/o/p 113/.notdef 114/r/s/t/u/v/w 120/.notdef 121/y 122/.notdef] >> endobj 315 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [298 0 R 317 0 R 332 0 R 345 0 R 365 0 R 394 0 R] >> endobj 434 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [424 0 R 436 0 R 440 0 R 454 0 R 458 0 R 463 0 R] >> endobj 474 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [472 0 R 476 0 R 479 0 R 483 0 R 491 0 R 498 0 R] >> endobj 509 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [503 0 R 511 0 R 515 0 R 527 0 R 532 0 R 536 0 R] >> endobj 544 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [541 0 R 546 0 R 550 0 R 554 0 R 558 0 R 562 0 R] >> endobj 571 0 obj << /Type /Pages /Count 6 /Parent 1144 0 R /Kids [567 0 R 573 0 R 577 0 R 581 0 R 585 0 R 589 0 R] >> endobj 597 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [594 0 R 599 0 R 603 0 R 607 0 R 611 0 R 615 0 R] >> endobj 622 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [619 0 R 624 0 R 628 0 R 632 0 R 636 0 R 640 0 R] >> endobj 647 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [644 0 R 649 0 R 653 0 R 657 0 R 661 0 R 665 0 R] >> endobj 672 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [669 0 R 674 0 R 678 0 R 682 0 R 686 0 R 690 0 R] >> endobj 697 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [694 0 R 699 0 R 703 0 R 707 0 R 711 0 R 715 0 R] >> endobj 722 0 obj << /Type /Pages /Count 6 /Parent 1145 0 R /Kids [719 0 R 724 0 R 728 0 R 732 0 R 736 0 R 740 0 R] >> endobj 747 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [744 0 R 749 0 R 753 0 R 757 0 R 764 0 R 768 0 R] >> endobj 775 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [772 0 R 777 0 R 781 0 R 785 0 R 789 0 R 793 0 R] >> endobj 800 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [797 0 R 802 0 R 806 0 R 810 0 R 814 0 R 818 0 R] >> endobj 825 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [822 0 R 827 0 R 831 0 R 835 0 R 839 0 R 843 0 R] >> endobj 850 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [847 0 R 852 0 R 856 0 R 860 0 R 864 0 R 868 0 R] >> endobj 875 0 obj << /Type /Pages /Count 6 /Parent 1146 0 R /Kids [872 0 R 877 0 R 881 0 R 885 0 R 889 0 R 893 0 R] >> endobj 900 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [897 0 R 902 0 R 906 0 R 910 0 R 914 0 R 918 0 R] >> endobj 925 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [922 0 R 927 0 R 931 0 R 935 0 R 939 0 R 943 0 R] >> endobj 953 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [947 0 R 955 0 R 959 0 R 964 0 R 968 0 R 972 0 R] >> endobj 979 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [976 0 R 981 0 R 985 0 R 989 0 R 993 0 R 997 0 R] >> endobj 1004 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [1001 0 R 1006 0 R 1010 0 R 1014 0 R 1018 0 R 1022 0 R] >> endobj 1029 0 obj << /Type /Pages /Count 6 /Parent 1147 0 R /Kids [1026 0 R 1031 0 R 1035 0 R 1040 0 R 1044 0 R 1048 0 R] >> endobj 1055 0 obj << /Type /Pages /Count 6 /Parent 1148 0 R /Kids [1052 0 R 1057 0 R 1061 0 R 1065 0 R 1069 0 R 1073 0 R] >> endobj 1080 0 obj << /Type /Pages /Count 6 /Parent 1148 0 R /Kids [1077 0 R 1082 0 R 1086 0 R 1090 0 R 1094 0 R 1098 0 R] >> endobj 1105 0 obj << /Type /Pages /Count 3 /Parent 1148 0 R /Kids [1102 0 R 1107 0 R 1111 0 R] >> endobj 1144 0 obj << /Type /Pages /Count 36 /Parent 1149 0 R /Kids [315 0 R 434 0 R 474 0 R 509 0 R 544 0 R 571 0 R] >> endobj 1145 0 obj << /Type /Pages /Count 36 /Parent 1149 0 R /Kids [597 0 R 622 0 R 647 0 R 672 0 R 697 0 R 722 0 R] >> endobj 1146 0 obj << /Type /Pages /Count 36 /Parent 1149 0 R /Kids [747 0 R 775 0 R 800 0 R 825 0 R 850 0 R 875 0 R] >> endobj 1147 0 obj << /Type /Pages /Count 36 /Parent 1149 0 R /Kids [900 0 R 925 0 R 953 0 R 979 0 R 1004 0 R 1029 0 R] >> endobj 1148 0 obj << /Type /Pages /Count 15 /Parent 1149 0 R /Kids [1055 0 R 1080 0 R 1105 0 R] >> endobj 1149 0 obj << /Type /Pages /Count 159 /Kids [1144 0 R 1145 0 R 1146 0 R 1147 0 R 1148 0 R] >> endobj 1150 0 obj << /Type /Outlines /First 7 0 R /Last 295 0 R /Count 19 >> endobj 295 0 obj << /Title 296 0 R /A 293 0 R /Parent 1150 0 R /Prev 291 0 R >> endobj 291 0 obj << /Title 292 0 R /A 289 0 R /Parent 1150 0 R /Prev 287 0 R /Next 295 0 R >> endobj 287 0 obj << /Title 288 0 R /A 285 0 R /Parent 1150 0 R /Prev 283 0 R /Next 291 0 R >> endobj 283 0 obj << /Title 284 0 R /A 281 0 R /Parent 1150 0 R /Prev 243 0 R /Next 287 0 R >> endobj 279 0 obj << /Title 280 0 R /A 277 0 R /Parent 243 0 R /Prev 275 0 R >> endobj 275 0 obj << /Title 276 0 R /A 273 0 R /Parent 243 0 R /Prev 271 0 R /Next 279 0 R >> endobj 271 0 obj << /Title 272 0 R /A 269 0 R /Parent 243 0 R /Prev 267 0 R /Next 275 0 R >> endobj 267 0 obj << /Title 268 0 R /A 265 0 R /Parent 243 0 R /Prev 263 0 R /Next 271 0 R >> endobj 263 0 obj << /Title 264 0 R /A 261 0 R /Parent 243 0 R /Prev 259 0 R /Next 267 0 R >> endobj 259 0 obj << /Title 260 0 R /A 257 0 R /Parent 243 0 R /Prev 255 0 R /Next 263 0 R >> endobj 255 0 obj << /Title 256 0 R /A 253 0 R /Parent 243 0 R /Prev 251 0 R /Next 259 0 R >> endobj 251 0 obj << /Title 252 0 R /A 249 0 R /Parent 243 0 R /Prev 247 0 R /Next 255 0 R >> endobj 247 0 obj << /Title 248 0 R /A 245 0 R /Parent 243 0 R /Next 251 0 R >> endobj 243 0 obj << /Title 244 0 R /A 241 0 R /Parent 1150 0 R /Prev 219 0 R /Next 283 0 R /First 247 0 R /Last 279 0 R /Count -9 >> endobj 239 0 obj << /Title 240 0 R /A 237 0 R /Parent 219 0 R /Prev 235 0 R >> endobj 235 0 obj << /Title 236 0 R /A 233 0 R /Parent 219 0 R /Prev 231 0 R /Next 239 0 R >> endobj 231 0 obj << /Title 232 0 R /A 229 0 R /Parent 219 0 R /Prev 227 0 R /Next 235 0 R >> endobj 227 0 obj << /Title 228 0 R /A 225 0 R /Parent 219 0 R /Prev 223 0 R /Next 231 0 R >> endobj 223 0 obj << /Title 224 0 R /A 221 0 R /Parent 219 0 R /Next 227 0 R >> endobj 219 0 obj << /Title 220 0 R /A 217 0 R /Parent 1150 0 R /Prev 199 0 R /Next 243 0 R /First 223 0 R /Last 239 0 R /Count -5 >> endobj 215 0 obj << /Title 216 0 R /A 213 0 R /Parent 199 0 R /Prev 211 0 R >> endobj 211 0 obj << /Title 212 0 R /A 209 0 R /Parent 199 0 R /Prev 207 0 R /Next 215 0 R >> endobj 207 0 obj << /Title 208 0 R /A 205 0 R /Parent 199 0 R /Prev 203 0 R /Next 211 0 R >> endobj 203 0 obj << /Title 204 0 R /A 201 0 R /Parent 199 0 R /Next 207 0 R >> endobj 199 0 obj << /Title 200 0 R /A 197 0 R /Parent 1150 0 R /Prev 179 0 R /Next 219 0 R /First 203 0 R /Last 215 0 R /Count -4 >> endobj 195 0 obj << /Title 196 0 R /A 193 0 R /Parent 179 0 R /Prev 191 0 R >> endobj 191 0 obj << /Title 192 0 R /A 189 0 R /Parent 179 0 R /Prev 187 0 R /Next 195 0 R >> endobj 187 0 obj << /Title 188 0 R /A 185 0 R /Parent 179 0 R /Prev 183 0 R /Next 191 0 R >> endobj 183 0 obj << /Title 184 0 R /A 181 0 R /Parent 179 0 R /Next 187 0 R >> endobj 179 0 obj << /Title 180 0 R /A 177 0 R /Parent 1150 0 R /Prev 163 0 R /Next 199 0 R /First 183 0 R /Last 195 0 R /Count -4 >> endobj 175 0 obj << /Title 176 0 R /A 173 0 R /Parent 163 0 R /Prev 171 0 R >> endobj 171 0 obj << /Title 172 0 R /A 169 0 R /Parent 163 0 R /Prev 167 0 R /Next 175 0 R >> endobj 167 0 obj << /Title 168 0 R /A 165 0 R /Parent 163 0 R /Next 171 0 R >> endobj 163 0 obj << /Title 164 0 R /A 161 0 R /Parent 1150 0 R /Prev 139 0 R /Next 179 0 R /First 167 0 R /Last 175 0 R /Count -3 >> endobj 159 0 obj << /Title 160 0 R /A 157 0 R /Parent 139 0 R /Prev 155 0 R >> endobj 155 0 obj << /Title 156 0 R /A 153 0 R /Parent 139 0 R /Prev 151 0 R /Next 159 0 R >> endobj 151 0 obj << /Title 152 0 R /A 149 0 R /Parent 139 0 R /Prev 147 0 R /Next 155 0 R >> endobj 147 0 obj << /Title 148 0 R /A 145 0 R /Parent 139 0 R /Prev 143 0 R /Next 151 0 R >> endobj 143 0 obj << /Title 144 0 R /A 141 0 R /Parent 139 0 R /Next 147 0 R >> endobj 139 0 obj << /Title 140 0 R /A 137 0 R /Parent 1150 0 R /Prev 131 0 R /Next 163 0 R /First 143 0 R /Last 159 0 R /Count -5 >> endobj 135 0 obj << /Title 136 0 R /A 133 0 R /Parent 131 0 R >> endobj 131 0 obj << /Title 132 0 R /A 129 0 R /Parent 1150 0 R /Prev 107 0 R /Next 139 0 R /First 135 0 R /Last 135 0 R /Count -1 >> endobj 127 0 obj << /Title 128 0 R /A 125 0 R /Parent 107 0 R /Prev 123 0 R >> endobj 123 0 obj << /Title 124 0 R /A 121 0 R /Parent 107 0 R /Prev 119 0 R /Next 127 0 R >> endobj 119 0 obj << /Title 120 0 R /A 117 0 R /Parent 107 0 R /Prev 115 0 R /Next 123 0 R >> endobj 115 0 obj << /Title 116 0 R /A 113 0 R /Parent 107 0 R /Prev 111 0 R /Next 119 0 R >> endobj 111 0 obj << /Title 112 0 R /A 109 0 R /Parent 107 0 R /Next 115 0 R >> endobj 107 0 obj << /Title 108 0 R /A 105 0 R /Parent 1150 0 R /Prev 87 0 R /Next 131 0 R /First 111 0 R /Last 127 0 R /Count -5 >> endobj 103 0 obj << /Title 104 0 R /A 101 0 R /Parent 87 0 R /Prev 99 0 R >> endobj 99 0 obj << /Title 100 0 R /A 97 0 R /Parent 87 0 R /Prev 95 0 R /Next 103 0 R >> endobj 95 0 obj << /Title 96 0 R /A 93 0 R /Parent 87 0 R /Prev 91 0 R /Next 99 0 R >> endobj 91 0 obj << /Title 92 0 R /A 89 0 R /Parent 87 0 R /Next 95 0 R >> endobj 87 0 obj << /Title 88 0 R /A 85 0 R /Parent 1150 0 R /Prev 67 0 R /Next 107 0 R /First 91 0 R /Last 103 0 R /Count -4 >> endobj 83 0 obj << /Title 84 0 R /A 81 0 R /Parent 67 0 R /Prev 79 0 R >> endobj 79 0 obj << /Title 80 0 R /A 77 0 R /Parent 67 0 R /Prev 75 0 R /Next 83 0 R >> endobj 75 0 obj << /Title 76 0 R /A 73 0 R /Parent 67 0 R /Prev 71 0 R /Next 79 0 R >> endobj 71 0 obj << /Title 72 0 R /A 69 0 R /Parent 67 0 R /Next 75 0 R >> endobj 67 0 obj << /Title 68 0 R /A 65 0 R /Parent 1150 0 R /Prev 31 0 R /Next 87 0 R /First 71 0 R /Last 83 0 R /Count -4 >> endobj 63 0 obj << /Title 64 0 R /A 61 0 R /Parent 31 0 R /Prev 59 0 R >> endobj 59 0 obj << /Title 60 0 R /A 57 0 R /Parent 31 0 R /Prev 55 0 R /Next 63 0 R >> endobj 55 0 obj << /Title 56 0 R /A 53 0 R /Parent 31 0 R /Prev 51 0 R /Next 59 0 R >> endobj 51 0 obj << /Title 52 0 R /A 49 0 R /Parent 31 0 R /Prev 47 0 R /Next 55 0 R >> endobj 47 0 obj << /Title 48 0 R /A 45 0 R /Parent 31 0 R /Prev 43 0 R /Next 51 0 R >> endobj 43 0 obj << /Title 44 0 R /A 41 0 R /Parent 31 0 R /Prev 39 0 R /Next 47 0 R >> endobj 39 0 obj << /Title 40 0 R /A 37 0 R /Parent 31 0 R /Prev 35 0 R /Next 43 0 R >> endobj 35 0 obj << /Title 36 0 R /A 33 0 R /Parent 31 0 R /Next 39 0 R >> endobj 31 0 obj << /Title 32 0 R /A 29 0 R /Parent 1150 0 R /Prev 19 0 R /Next 67 0 R /First 35 0 R /Last 63 0 R /Count -8 >> endobj 27 0 obj << /Title 28 0 R /A 25 0 R /Parent 19 0 R /Prev 23 0 R >> endobj 23 0 obj << /Title 24 0 R /A 21 0 R /Parent 19 0 R /Next 27 0 R >> endobj 19 0 obj << /Title 20 0 R /A 17 0 R /Parent 1150 0 R /Prev 15 0 R /Next 31 0 R /First 23 0 R /Last 27 0 R /Count -2 >> endobj 15 0 obj << /Title 16 0 R /A 13 0 R /Parent 1150 0 R /Prev 11 0 R /Next 19 0 R >> endobj 11 0 obj << /Title 12 0 R /A 9 0 R /Parent 1150 0 R /Prev 7 0 R /Next 15 0 R >> endobj 7 0 obj << /Title 8 0 R /A 5 0 R /Parent 1150 0 R /Next 11 0 R >> endobj 1151 0 obj << /Names [(Doc-Start) 303 0 R (Item.1) 494 0 R (Item.2) 495 0 R (Item.3) 496 0 R (Item.4) 506 0 R (Item.5) 507 0 R (Item.6) 508 0 R (chapter*.3) 348 0 R (chapter.1) 14 0 R (chapter.10) 178 0 R (chapter.11) 198 0 R (chapter.12) 218 0 R (chapter.13) 242 0 R (chapter.14) 282 0 R (chapter.15) 286 0 R (chapter.16) 290 0 R (chapter.17) 294 0 R (chapter.2) 18 0 R (chapter.3) 30 0 R (chapter.4) 66 0 R (chapter.5) 86 0 R (chapter.6) 106 0 R (chapter.7) 130 0 R (chapter.8) 138 0 R (chapter.9) 162 0 R (page.1) 302 0 R (page.10) 500 0 R (page.100) 895 0 R (page.101) 899 0 R (page.102) 904 0 R (page.103) 908 0 R (page.104) 912 0 R (page.105) 916 0 R (page.106) 920 0 R (page.107) 924 0 R (page.108) 929 0 R (page.109) 933 0 R (page.11) 505 0 R (page.110) 937 0 R (page.111) 941 0 R (page.112) 945 0 R (page.113) 949 0 R (page.114) 957 0 R (page.115) 961 0 R (page.116) 966 0 R (page.117) 970 0 R (page.118) 974 0 R (page.119) 978 0 R (page.12) 513 0 R (page.120) 983 0 R (page.121) 987 0 R (page.122) 991 0 R (page.123) 995 0 R (page.124) 999 0 R (page.125) 1003 0 R (page.126) 1008 0 R (page.127) 1012 0 R (page.128) 1016 0 R (page.129) 1020 0 R (page.13) 517 0 R (page.130) 1024 0 R (page.131) 1028 0 R (page.132) 1033 0 R (page.133) 1037 0 R (page.134) 1042 0 R (page.135) 1046 0 R (page.136) 1050 0 R (page.137) 1054 0 R (page.138) 1059 0 R (page.139) 1063 0 R (page.14) 529 0 R (page.140) 1067 0 R (page.141) 1071 0 R (page.142) 1075 0 R (page.143) 1079 0 R (page.144) 1084 0 R (page.145) 1088 0 R (page.146) 1092 0 R (page.147) 1096 0 R (page.148) 1100 0 R (page.149) 1104 0 R (page.15) 534 0 R (page.150) 1109 0 R (page.151) 1113 0 R (page.16) 538 0 R (page.17) 543 0 R (page.18) 548 0 R (page.19) 552 0 R (page.2) 334 0 R (page.20) 556 0 R (page.21) 560 0 R (page.22) 564 0 R (page.23) 569 0 R (page.24) 575 0 R (page.25) 579 0 R (page.26) 583 0 R (page.27) 587 0 R (page.28) 591 0 R (page.29) 596 0 R (page.3) 347 0 R (page.30) 601 0 R (page.31) 605 0 R (page.32) 609 0 R (page.33) 613 0 R (page.34) 617 0 R (page.35) 621 0 R (page.36) 626 0 R (page.37) 630 0 R (page.38) 634 0 R (page.39) 638 0 R (page.4) 367 0 R (page.40) 642 0 R (page.41) 646 0 R (page.42) 651 0 R (page.43) 655 0 R (page.44) 659 0 R (page.45) 663 0 R (page.46) 667 0 R (page.47) 671 0 R (page.48) 676 0 R (page.49) 680 0 R (page.5) 396 0 R (page.50) 684 0 R (page.51) 688 0 R (page.52) 692 0 R (page.53) 696 0 R (page.54) 701 0 R (page.55) 705 0 R (page.56) 709 0 R (page.57) 713 0 R (page.58) 717 0 R (page.59) 721 0 R (page.6) 426 0 R (page.60) 726 0 R (page.61) 730 0 R (page.62) 734 0 R (page.63) 738 0 R (page.64) 742 0 R (page.65) 746 0 R (page.66) 751 0 R (page.67) 755 0 R (page.68) 759 0 R (page.69) 766 0 R (page.7) 438 0 R (page.70) 770 0 R (page.71) 774 0 R (page.72) 779 0 R (page.73) 783 0 R (page.74) 787 0 R (page.75) 791 0 R (page.76) 795 0 R (page.77) 799 0 R (page.78) 804 0 R (page.79) 808 0 R (page.8) 485 0 R (page.80) 812 0 R (page.81) 816 0 R (page.82) 820 0 R (page.83) 824 0 R (page.84) 829 0 R (page.85) 833 0 R (page.86) 837 0 R (page.87) 841 0 R (page.88) 845 0 R (page.89) 849 0 R (page.9) 493 0 R (page.90) 854 0 R (page.91) 858 0 R (page.92) 862 0 R (page.93) 866 0 R (page.94) 870 0 R (page.95) 874 0 R (page.96) 879 0 R (page.97) 883 0 R (page.98) 887 0 R (page.99) 891 0 R (part*.27) 592 0 R (part*.4) 442 0 R (section*.1) 6 0 R (section*.10) 26 0 R (section*.11) 34 0 R (section*.12) 501 0 R (section*.13) 38 0 R (section*.14) 518 0 R (section*.15) 521 0 R (section*.16) 524 0 R (section*.17) 42 0 R (section*.18) 530 0 R (section*.19) 539 0 R (section*.2) 10 0 R (section*.20) 46 0 R (section*.21) 50 0 R (section*.22) 54 0 R (section*.23) 565 0 R (section*.24) 570 0 R (section*.25) 58 0 R (section*.26) 62 0 R (section*.28) 70 0 R (section*.29) 74 0 R (section*.30) 78 0 R (section*.31) 82 0 R (section*.32) 90 0 R (section*.33) 94 0 R (section*.34) 98 0 R (section*.35) 102 0 R (section*.36) 110 0 R (section*.37) 114 0 R (section*.38) 118 0 R (section*.39) 122 0 R (section*.40) 126 0 R (section*.41) 134 0 R (section*.42) 142 0 R (section*.43) 146 0 R (section*.44) 150 0 R (section*.45) 154 0 R (section*.46) 158 0 R (section*.47) 166 0 R (section*.48) 170 0 R (section*.49) 174 0 R (section*.5) 452 0 R (section*.50) 182 0 R (section*.51) 186 0 R (section*.52) 190 0 R (section*.53) 194 0 R (section*.54) 202 0 R (section*.55) 206 0 R (section*.56) 210 0 R (section*.57) 214 0 R (section*.58) 760 0 R (section*.59) 761 0 R (section*.6) 456 0 R (section*.60) 762 0 R (section*.61) 222 0 R (section*.62) 226 0 R (section*.63) 230 0 R (section*.64) 234 0 R (section*.65) 238 0 R (section*.66) 246 0 R (section*.67) 250 0 R (section*.68) 254 0 R (section*.69) 258 0 R (section*.7) 22 0 R (section*.70) 262 0 R (section*.71) 266 0 R (section*.72) 270 0 R (section*.73) 274 0 R (section*.74) 278 0 R (section*.8) 465 0 R (section*.9) 466 0 R (ugen_FM) 1038 0 R (ugen_STK) 962 0 R] /Limits [(Doc-Start) (ugen_STK)] >> endobj 1152 0 obj << /Kids [1151 0 R] >> endobj 1153 0 obj << /Dests 1152 0 R >> endobj 1154 0 obj << /Type /Catalog /Pages 1149 0 R /Outlines 1150 0 R /Names 1153 0 R /PageMode /UseOutlines /OpenAction 297 0 R >> endobj 1155 0 obj << /Author()/Title()/Subject()/Creator(LaTeX with hyperref package)/Producer(pdfeTeX-1.21a)/Keywords() /CreationDate (D:20070322020530-04'00') /PTEX.Fullbanner (This is pdfeTeX, Version 3.141592-1.21a-2.2 (Web2C 7.5.4) kpathsea version 3.5.4) >> endobj xref 0 1156 0000000001 65535 f 0000000002 00000 f 0000000003 00000 f 0000000004 00000 f 0000000000 00000 f 0000000009 00000 n 0000025045 00000 n 0000571744 00000 n 0000000055 00000 n 0000000089 00000 n 0000028302 00000 n 0000571657 00000 n 0000000135 00000 n 0000000166 00000 n 0000051409 00000 n 0000571568 00000 n 0000000212 00000 n 0000000247 00000 n 0000054917 00000 n 0000571442 00000 n 0000000293 00000 n 0000000324 00000 n 0000054974 00000 n 0000571368 00000 n 0000000371 00000 n 0000000409 00000 n 0000126562 00000 n 0000571294 00000 n 0000000457 00000 n 0000000495 00000 n 0000130942 00000 n 0000571168 00000 n 0000000541 00000 n 0000000575 00000 n 0000130999 00000 n 0000571094 00000 n 0000000623 00000 n 0000000658 00000 n 0000143638 00000 n 0000571007 00000 n 0000000706 00000 n 0000000736 00000 n 0000146298 00000 n 0000570920 00000 n 0000000784 00000 n 0000000825 00000 n 0000167960 00000 n 0000570833 00000 n 0000000873 00000 n 0000000915 00000 n 0000173115 00000 n 0000570746 00000 n 0000000963 00000 n 0000001000 00000 n 0000176592 00000 n 0000570659 00000 n 0000001048 00000 n 0000001084 00000 n 0000183136 00000 n 0000570572 00000 n 0000001132 00000 n 0000001166 00000 n 0000187403 00000 n 0000570498 00000 n 0000001214 00000 n 0000001239 00000 n 0000190289 00000 n 0000570372 00000 n 0000001285 00000 n 0000001312 00000 n 0000190346 00000 n 0000570298 00000 n 0000001360 00000 n 0000001392 00000 n 0000193401 00000 n 0000570211 00000 n 0000001440 00000 n 0000001467 00000 n 0000195619 00000 n 0000570124 00000 n 0000001515 00000 n 0000001545 00000 n 0000197379 00000 n 0000570050 00000 n 0000001593 00000 n 0000001626 00000 n 0000203257 00000 n 0000569922 00000 n 0000001672 00000 n 0000001719 00000 n 0000203314 00000 n 0000569848 00000 n 0000001767 00000 n 0000001801 00000 n 0000205711 00000 n 0000569761 00000 n 0000001849 00000 n 0000001887 00000 n 0000205768 00000 n 0000569672 00000 n 0000001935 00000 n 0000001964 00000 n 0000209285 00000 n 0000569595 00000 n 0000002013 00000 n 0000002048 00000 n 0000211121 00000 n 0000569463 00000 n 0000002095 00000 n 0000002121 00000 n 0000211179 00000 n 0000569384 00000 n 0000002170 00000 n 0000002201 00000 n 0000213541 00000 n 0000569291 00000 n 0000002250 00000 n 0000002294 00000 n 0000215161 00000 n 0000569198 00000 n 0000002343 00000 n 0000002369 00000 n 0000218358 00000 n 0000569105 00000 n 0000002418 00000 n 0000002456 00000 n 0000220302 00000 n 0000569026 00000 n 0000002505 00000 n 0000002541 00000 n 0000225119 00000 n 0000568893 00000 n 0000002588 00000 n 0000002632 00000 n 0000230612 00000 n 0000568828 00000 n 0000002681 00000 n 0000002705 00000 n 0000236234 00000 n 0000568695 00000 n 0000002752 00000 n 0000002790 00000 n 0000236292 00000 n 0000568616 00000 n 0000002839 00000 n 0000002868 00000 n 0000238187 00000 n 0000568523 00000 n 0000002917 00000 n 0000002942 00000 n 0000238245 00000 n 0000568430 00000 n 0000002991 00000 n 0000003016 00000 n 0000240176 00000 n 0000568337 00000 n 0000003065 00000 n 0000003088 00000 n 0000240234 00000 n 0000568258 00000 n 0000003137 00000 n 0000003173 00000 n 0000242957 00000 n 0000568125 00000 n 0000003220 00000 n 0000003249 00000 n 0000243015 00000 n 0000568046 00000 n 0000003298 00000 n 0000003325 00000 n 0000244582 00000 n 0000567953 00000 n 0000003374 00000 n 0000003401 00000 n 0000244640 00000 n 0000567874 00000 n 0000003450 00000 n 0000003481 00000 n 0000247919 00000 n 0000567741 00000 n 0000003529 00000 n 0000003571 00000 n 0000250091 00000 n 0000567662 00000 n 0000003620 00000 n 0000003667 00000 n 0000252108 00000 n 0000567569 00000 n 0000003716 00000 n 0000003752 00000 n 0000253889 00000 n 0000567476 00000 n 0000003801 00000 n 0000003842 00000 n 0000255165 00000 n 0000567397 00000 n 0000003891 00000 n 0000003936 00000 n 0000257154 00000 n 0000567264 00000 n 0000003984 00000 n 0000004019 00000 n 0000257212 00000 n 0000567185 00000 n 0000004068 00000 n 0000004105 00000 n 0000259292 00000 n 0000567092 00000 n 0000004154 00000 n 0000004220 00000 n 0000263235 00000 n 0000566999 00000 n 0000004269 00000 n 0000004306 00000 n 0000263293 00000 n 0000566920 00000 n 0000004355 00000 n 0000004389 00000 n 0000268398 00000 n 0000566787 00000 n 0000004437 00000 n 0000004463 00000 n 0000268456 00000 n 0000566708 00000 n 0000004512 00000 n 0000004545 00000 n 0000269733 00000 n 0000566615 00000 n 0000004594 00000 n 0000004617 00000 n 0000271726 00000 n 0000566522 00000 n 0000004666 00000 n 0000004697 00000 n 0000273401 00000 n 0000566429 00000 n 0000004746 00000 n 0000004776 00000 n 0000275139 00000 n 0000566350 00000 n 0000004825 00000 n 0000004867 00000 n 0000278233 00000 n 0000566217 00000 n 0000004915 00000 n 0000004942 00000 n 0000278291 00000 n 0000566138 00000 n 0000004991 00000 n 0000005023 00000 n 0000280828 00000 n 0000566045 00000 n 0000005072 00000 n 0000005108 00000 n 0000280886 00000 n 0000565952 00000 n 0000005157 00000 n 0000005197 00000 n 0000283357 00000 n 0000565859 00000 n 0000005246 00000 n 0000005281 00000 n 0000285434 00000 n 0000565766 00000 n 0000005330 00000 n 0000005387 00000 n 0000288342 00000 n 0000565673 00000 n 0000005436 00000 n 0000005474 00000 n 0000288400 00000 n 0000565580 00000 n 0000005523 00000 n 0000005570 00000 n 0000290152 00000 n 0000565487 00000 n 0000005619 00000 n 0000005650 00000 n 0000294440 00000 n 0000565408 00000 n 0000005699 00000 n 0000005730 00000 n 0000296969 00000 n 0000565314 00000 n 0000005778 00000 n 0000005834 00000 n 0000304569 00000 n 0000565220 00000 n 0000005882 00000 n 0000005933 00000 n 0000309735 00000 n 0000565126 00000 n 0000005981 00000 n 0000006023 00000 n 0000323198 00000 n 0000565046 00000 n 0000006071 00000 n 0000006106 00000 n 0000006819 00000 n 0000006951 00000 n 0000022939 00000 n 0000006158 00000 n 0000022828 00000 n 0000022881 00000 n 0000560102 00000 n 0000551715 00000 n 0000559939 00000 n 0000550084 00000 n 0000531404 00000 n 0000549921 00000 n 0000022646 00000 n 0000530447 00000 n 0000522459 00000 n 0000530284 00000 n 0000521974 00000 n 0000561093 00000 n 0000025101 00000 n 0000024933 00000 n 0000023086 00000 n 0000520838 00000 n 0000518843 00000 n 0000520675 00000 n 0000517749 00000 n 0000508333 00000 n 0000517585 00000 n 0000507048 00000 n 0000491848 00000 n 0000506884 00000 n 0000491526 00000 n 0000489299 00000 n 0000491363 00000 n 0000028359 00000 n 0000026373 00000 n 0000025238 00000 n 0000028249 00000 n 0000026569 00000 n 0000026750 00000 n 0000026934 00000 n 0000027119 00000 n 0000027308 00000 n 0000027501 00000 n 0000027693 00000 n 0000027878 00000 n 0000028061 00000 n 0000032802 00000 n 0000030102 00000 n 0000028483 00000 n 0000032691 00000 n 0000032744 00000 n 0000030346 00000 n 0000030502 00000 n 0000030658 00000 n 0000030813 00000 n 0000030968 00000 n 0000031124 00000 n 0000031281 00000 n 0000031436 00000 n 0000031593 00000 n 0000031750 00000 n 0000031907 00000 n 0000032063 00000 n 0000032220 00000 n 0000032377 00000 n 0000032534 00000 n 0000039387 00000 n 0000035105 00000 n 0000032913 00000 n 0000039334 00000 n 0000035429 00000 n 0000035584 00000 n 0000035741 00000 n 0000035898 00000 n 0000036054 00000 n 0000036211 00000 n 0000036366 00000 n 0000036522 00000 n 0000036679 00000 n 0000036836 00000 n 0000036993 00000 n 0000037148 00000 n 0000037305 00000 n 0000037462 00000 n 0000037617 00000 n 0000037774 00000 n 0000037931 00000 n 0000038085 00000 n 0000038242 00000 n 0000038397 00000 n 0000038553 00000 n 0000038710 00000 n 0000038866 00000 n 0000039023 00000 n 0000039180 00000 n 0000046367 00000 n 0000041915 00000 n 0000039498 00000 n 0000046314 00000 n 0000042247 00000 n 0000042404 00000 n 0000042561 00000 n 0000042718 00000 n 0000042874 00000 n 0000043031 00000 n 0000043188 00000 n 0000043345 00000 n 0000043501 00000 n 0000043657 00000 n 0000043812 00000 n 0000043969 00000 n 0000044124 00000 n 0000044281 00000 n 0000044437 00000 n 0000044593 00000 n 0000044750 00000 n 0000044906 00000 n 0000045063 00000 n 0000045220 00000 n 0000045375 00000 n 0000045532 00000 n 0000045688 00000 n 0000045845 00000 n 0000046001 00000 n 0000046157 00000 n 0000048829 00000 n 0000047503 00000 n 0000046478 00000 n 0000048776 00000 n 0000047683 00000 n 0000047839 00000 n 0000047995 00000 n 0000048152 00000 n 0000048308 00000 n 0000048464 00000 n 0000048620 00000 n 0000561211 00000 n 0000049455 00000 n 0000049290 00000 n 0000048940 00000 n 0000049402 00000 n 0000051524 00000 n 0000051239 00000 n 0000049566 00000 n 0000051351 00000 n 0000489004 00000 n 0000485459 00000 n 0000488832 00000 n 0000485139 00000 n 0000476738 00000 n 0000484964 00000 n 0000473422 00000 n 0000455950 00000 n 0000473258 00000 n 0000051466 00000 n 0000052804 00000 n 0000052634 00000 n 0000051700 00000 n 0000052746 00000 n 0000055031 00000 n 0000054597 00000 n 0000052928 00000 n 0000054729 00000 n 0000058344 00000 n 0000057244 00000 n 0000057016 00000 n 0000055181 00000 n 0000057128 00000 n 0000057186 00000 n 0000455462 00000 n 0000453403 00000 n 0000455298 00000 n 0000091655 00000 n 0000123993 00000 n 0000058232 00000 n 0000057381 00000 n 0000561329 00000 n 0000126619 00000 n 0000126450 00000 n 0000124153 00000 n 0000128807 00000 n 0000128490 00000 n 0000126743 00000 n 0000128622 00000 n 0000131056 00000 n 0000130568 00000 n 0000128918 00000 n 0000130889 00000 n 0000130700 00000 n 0000451902 00000 n 0000435598 00000 n 0000451738 00000 n 0000134310 00000 n 0000133971 00000 n 0000131232 00000 n 0000134083 00000 n 0000134136 00000 n 0000134194 00000 n 0000134252 00000 n 0000137164 00000 n 0000136941 00000 n 0000134434 00000 n 0000137053 00000 n 0000137106 00000 n 0000139614 00000 n 0000139276 00000 n 0000137301 00000 n 0000139388 00000 n 0000139441 00000 n 0000139499 00000 n 0000139556 00000 n 0000561447 00000 n 0000140804 00000 n 0000140639 00000 n 0000139738 00000 n 0000140751 00000 n 0000143869 00000 n 0000142676 00000 n 0000140915 00000 n 0000143585 00000 n 0000143695 00000 n 0000142832 00000 n 0000143019 00000 n 0000143753 00000 n 0000143220 00000 n 0000143412 00000 n 0000143811 00000 n 0000148853 00000 n 0000146413 00000 n 0000146133 00000 n 0000143993 00000 n 0000146245 00000 n 0000146355 00000 n 0000162947 00000 n 0000148741 00000 n 0000146537 00000 n 0000162894 00000 n 0000165062 00000 n 0000164839 00000 n 0000163094 00000 n 0000164951 00000 n 0000165004 00000 n 0000168017 00000 n 0000167795 00000 n 0000165186 00000 n 0000167907 00000 n 0000561565 00000 n 0000170284 00000 n 0000170119 00000 n 0000168154 00000 n 0000170231 00000 n 0000173172 00000 n 0000172950 00000 n 0000170408 00000 n 0000173062 00000 n 0000174136 00000 n 0000173971 00000 n 0000173309 00000 n 0000174083 00000 n 0000176649 00000 n 0000176427 00000 n 0000174247 00000 n 0000176539 00000 n 0000179456 00000 n 0000179233 00000 n 0000176786 00000 n 0000179345 00000 n 0000179398 00000 n 0000180833 00000 n 0000180610 00000 n 0000179593 00000 n 0000180722 00000 n 0000180775 00000 n 0000561683 00000 n 0000183193 00000 n 0000182971 00000 n 0000180970 00000 n 0000183083 00000 n 0000185443 00000 n 0000185278 00000 n 0000183330 00000 n 0000185390 00000 n 0000187460 00000 n 0000187238 00000 n 0000185567 00000 n 0000187350 00000 n 0000188098 00000 n 0000187933 00000 n 0000187597 00000 n 0000188045 00000 n 0000190402 00000 n 0000190066 00000 n 0000188209 00000 n 0000190178 00000 n 0000190231 00000 n 0000193458 00000 n 0000193236 00000 n 0000190578 00000 n 0000193348 00000 n 0000561801 00000 n 0000195676 00000 n 0000195454 00000 n 0000193595 00000 n 0000195566 00000 n 0000197436 00000 n 0000197214 00000 n 0000195813 00000 n 0000197326 00000 n 0000199299 00000 n 0000199134 00000 n 0000197586 00000 n 0000199246 00000 n 0000200924 00000 n 0000200759 00000 n 0000199423 00000 n 0000200871 00000 n 0000203371 00000 n 0000203092 00000 n 0000201061 00000 n 0000203204 00000 n 0000205825 00000 n 0000205546 00000 n 0000203534 00000 n 0000205658 00000 n 0000561919 00000 n 0000207796 00000 n 0000207631 00000 n 0000205962 00000 n 0000207743 00000 n 0000209343 00000 n 0000209120 00000 n 0000207920 00000 n 0000209232 00000 n 0000211237 00000 n 0000210956 00000 n 0000209480 00000 n 0000211068 00000 n 0000213599 00000 n 0000213376 00000 n 0000211413 00000 n 0000213488 00000 n 0000215219 00000 n 0000214996 00000 n 0000213749 00000 n 0000215108 00000 n 0000216664 00000 n 0000216499 00000 n 0000215356 00000 n 0000216611 00000 n 0000562037 00000 n 0000218416 00000 n 0000218193 00000 n 0000216788 00000 n 0000218305 00000 n 0000220360 00000 n 0000220137 00000 n 0000218553 00000 n 0000220249 00000 n 0000222010 00000 n 0000221845 00000 n 0000220497 00000 n 0000221957 00000 n 0000222876 00000 n 0000222711 00000 n 0000222134 00000 n 0000222823 00000 n 0000225177 00000 n 0000224954 00000 n 0000223000 00000 n 0000225066 00000 n 0000227268 00000 n 0000227103 00000 n 0000225340 00000 n 0000227215 00000 n 0000562155 00000 n 0000229075 00000 n 0000228910 00000 n 0000227392 00000 n 0000229022 00000 n 0000230670 00000 n 0000230447 00000 n 0000229199 00000 n 0000230559 00000 n 0000232819 00000 n 0000232654 00000 n 0000230807 00000 n 0000232766 00000 n 0000234716 00000 n 0000234551 00000 n 0000232969 00000 n 0000234663 00000 n 0000236350 00000 n 0000236069 00000 n 0000234866 00000 n 0000236181 00000 n 0000238303 00000 n 0000238022 00000 n 0000236513 00000 n 0000238134 00000 n 0000562273 00000 n 0000240292 00000 n 0000240011 00000 n 0000238453 00000 n 0000240123 00000 n 0000241404 00000 n 0000241239 00000 n 0000240442 00000 n 0000241351 00000 n 0000243073 00000 n 0000242792 00000 n 0000241528 00000 n 0000242904 00000 n 0000244698 00000 n 0000244417 00000 n 0000243236 00000 n 0000244529 00000 n 0000245602 00000 n 0000245437 00000 n 0000244835 00000 n 0000245549 00000 n 0000247977 00000 n 0000247754 00000 n 0000245726 00000 n 0000247866 00000 n 0000562391 00000 n 0000250149 00000 n 0000249926 00000 n 0000248127 00000 n 0000250038 00000 n 0000252166 00000 n 0000251943 00000 n 0000250312 00000 n 0000252055 00000 n 0000253946 00000 n 0000253724 00000 n 0000252303 00000 n 0000253836 00000 n 0000255223 00000 n 0000255000 00000 n 0000254083 00000 n 0000255112 00000 n 0000257269 00000 n 0000256989 00000 n 0000255347 00000 n 0000257101 00000 n 0000259350 00000 n 0000259127 00000 n 0000257458 00000 n 0000259239 00000 n 0000562509 00000 n 0000260745 00000 n 0000260580 00000 n 0000259500 00000 n 0000260692 00000 n 0000263351 00000 n 0000263070 00000 n 0000260869 00000 n 0000263182 00000 n 0000265117 00000 n 0000264778 00000 n 0000263501 00000 n 0000264890 00000 n 0000264943 00000 n 0000265001 00000 n 0000265059 00000 n 0000266682 00000 n 0000266517 00000 n 0000265254 00000 n 0000266629 00000 n 0000268514 00000 n 0000268233 00000 n 0000266806 00000 n 0000268345 00000 n 0000269791 00000 n 0000269568 00000 n 0000268677 00000 n 0000269680 00000 n 0000562627 00000 n 0000271784 00000 n 0000271561 00000 n 0000269928 00000 n 0000271673 00000 n 0000273459 00000 n 0000273236 00000 n 0000271921 00000 n 0000273348 00000 n 0000275197 00000 n 0000274974 00000 n 0000273596 00000 n 0000275086 00000 n 0000276131 00000 n 0000275966 00000 n 0000275347 00000 n 0000276078 00000 n 0000278349 00000 n 0000278068 00000 n 0000276255 00000 n 0000278180 00000 n 0000280944 00000 n 0000280663 00000 n 0000278525 00000 n 0000280775 00000 n 0000562745 00000 n 0000283415 00000 n 0000283192 00000 n 0000281107 00000 n 0000283304 00000 n 0000285492 00000 n 0000285269 00000 n 0000283565 00000 n 0000285381 00000 n 0000286640 00000 n 0000286475 00000 n 0000285642 00000 n 0000286587 00000 n 0000288458 00000 n 0000288177 00000 n 0000286764 00000 n 0000288289 00000 n 0000290210 00000 n 0000289987 00000 n 0000288608 00000 n 0000290099 00000 n 0000291647 00000 n 0000291482 00000 n 0000290347 00000 n 0000291594 00000 n 0000562863 00000 n 0000293076 00000 n 0000292911 00000 n 0000291771 00000 n 0000293023 00000 n 0000294497 00000 n 0000294275 00000 n 0000293200 00000 n 0000294387 00000 n 0000297027 00000 n 0000296804 00000 n 0000294634 00000 n 0000296916 00000 n 0000300057 00000 n 0000299892 00000 n 0000297190 00000 n 0000300004 00000 n 0000302330 00000 n 0000302165 00000 n 0000300168 00000 n 0000302277 00000 n 0000304627 00000 n 0000304404 00000 n 0000302441 00000 n 0000304516 00000 n 0000562981 00000 n 0000306865 00000 n 0000306700 00000 n 0000304777 00000 n 0000306812 00000 n 0000307944 00000 n 0000307779 00000 n 0000306976 00000 n 0000307891 00000 n 0000309793 00000 n 0000309570 00000 n 0000308055 00000 n 0000309682 00000 n 0000312295 00000 n 0000312130 00000 n 0000309943 00000 n 0000312242 00000 n 0000314762 00000 n 0000314597 00000 n 0000312406 00000 n 0000314709 00000 n 0000317141 00000 n 0000316976 00000 n 0000314886 00000 n 0000317088 00000 n 0000563099 00000 n 0000319395 00000 n 0000319230 00000 n 0000317278 00000 n 0000319342 00000 n 0000321670 00000 n 0000321505 00000 n 0000319506 00000 n 0000321617 00000 n 0000323256 00000 n 0000323033 00000 n 0000321781 00000 n 0000323145 00000 n 0000325358 00000 n 0000325193 00000 n 0000323419 00000 n 0000325305 00000 n 0000327426 00000 n 0000327261 00000 n 0000325508 00000 n 0000327373 00000 n 0000329272 00000 n 0000329107 00000 n 0000327576 00000 n 0000329219 00000 n 0000563217 00000 n 0000331184 00000 n 0000331019 00000 n 0000329435 00000 n 0000331131 00000 n 0000333331 00000 n 0000333166 00000 n 0000331347 00000 n 0000333278 00000 n 0000335258 00000 n 0000335093 00000 n 0000333494 00000 n 0000335205 00000 n 0000337046 00000 n 0000336881 00000 n 0000335408 00000 n 0000336993 00000 n 0000338991 00000 n 0000338826 00000 n 0000337196 00000 n 0000338938 00000 n 0000340914 00000 n 0000340749 00000 n 0000339141 00000 n 0000340861 00000 n 0000563335 00000 n 0000342750 00000 n 0000342585 00000 n 0000341051 00000 n 0000342697 00000 n 0000345695 00000 n 0000345530 00000 n 0000342887 00000 n 0000345642 00000 n 0000347653 00000 n 0000347488 00000 n 0000345845 00000 n 0000347600 00000 n 0000349590 00000 n 0000349425 00000 n 0000347803 00000 n 0000349537 00000 n 0000351640 00000 n 0000351475 00000 n 0000349727 00000 n 0000351587 00000 n 0000353726 00000 n 0000353561 00000 n 0000351790 00000 n 0000353673 00000 n 0000435245 00000 n 0000433243 00000 n 0000435082 00000 n 0000563453 00000 n 0000355693 00000 n 0000355528 00000 n 0000353889 00000 n 0000355640 00000 n 0000358133 00000 n 0000357904 00000 n 0000355856 00000 n 0000358016 00000 n 0000358069 00000 n 0000360484 00000 n 0000360319 00000 n 0000358283 00000 n 0000360431 00000 n 0000362741 00000 n 0000362576 00000 n 0000360634 00000 n 0000362688 00000 n 0000365129 00000 n 0000364964 00000 n 0000362891 00000 n 0000365076 00000 n 0000367553 00000 n 0000367388 00000 n 0000365279 00000 n 0000367500 00000 n 0000563571 00000 n 0000369931 00000 n 0000369766 00000 n 0000367703 00000 n 0000369878 00000 n 0000372456 00000 n 0000372291 00000 n 0000370081 00000 n 0000372403 00000 n 0000374826 00000 n 0000374661 00000 n 0000372606 00000 n 0000374773 00000 n 0000376875 00000 n 0000376710 00000 n 0000374976 00000 n 0000376822 00000 n 0000379472 00000 n 0000379307 00000 n 0000377025 00000 n 0000379419 00000 n 0000381862 00000 n 0000381691 00000 n 0000379622 00000 n 0000381807 00000 n 0000563689 00000 n 0000384482 00000 n 0000384311 00000 n 0000382013 00000 n 0000384427 00000 n 0000385890 00000 n 0000385719 00000 n 0000384633 00000 n 0000385835 00000 n 0000388135 00000 n 0000387964 00000 n 0000386015 00000 n 0000388080 00000 n 0000390529 00000 n 0000390358 00000 n 0000388286 00000 n 0000390474 00000 n 0000393044 00000 n 0000392873 00000 n 0000390680 00000 n 0000392989 00000 n 0000395304 00000 n 0000395133 00000 n 0000393195 00000 n 0000395249 00000 n 0000563814 00000 n 0000397322 00000 n 0000397151 00000 n 0000395468 00000 n 0000397267 00000 n 0000399079 00000 n 0000398842 00000 n 0000397473 00000 n 0000398958 00000 n 0000399013 00000 n 0000400920 00000 n 0000400749 00000 n 0000399230 00000 n 0000400865 00000 n 0000402596 00000 n 0000402425 00000 n 0000401071 00000 n 0000402541 00000 n 0000404232 00000 n 0000404061 00000 n 0000402734 00000 n 0000404177 00000 n 0000405864 00000 n 0000405693 00000 n 0000404370 00000 n 0000405809 00000 n 0000563939 00000 n 0000407673 00000 n 0000407502 00000 n 0000406002 00000 n 0000407618 00000 n 0000409545 00000 n 0000409374 00000 n 0000407824 00000 n 0000409490 00000 n 0000411424 00000 n 0000411253 00000 n 0000409696 00000 n 0000411369 00000 n 0000413508 00000 n 0000413337 00000 n 0000411588 00000 n 0000413453 00000 n 0000415695 00000 n 0000415524 00000 n 0000413659 00000 n 0000415640 00000 n 0000417426 00000 n 0000417255 00000 n 0000415859 00000 n 0000417371 00000 n 0000564064 00000 n 0000419311 00000 n 0000419140 00000 n 0000417590 00000 n 0000419256 00000 n 0000421184 00000 n 0000421013 00000 n 0000419462 00000 n 0000421129 00000 n 0000423274 00000 n 0000423103 00000 n 0000421348 00000 n 0000423219 00000 n 0000425406 00000 n 0000425235 00000 n 0000423425 00000 n 0000425351 00000 n 0000427160 00000 n 0000426989 00000 n 0000425570 00000 n 0000427105 00000 n 0000429174 00000 n 0000429003 00000 n 0000427298 00000 n 0000429119 00000 n 0000564189 00000 n 0000431924 00000 n 0000431753 00000 n 0000429312 00000 n 0000431869 00000 n 0000433105 00000 n 0000432934 00000 n 0000432062 00000 n 0000433050 00000 n 0000435490 00000 n 0000435459 00000 n 0000452883 00000 n 0000452492 00000 n 0000455775 00000 n 0000455710 00000 n 0000474293 00000 n 0000473902 00000 n 0000474849 00000 n 0000485398 00000 n 0000489224 00000 n 0000491758 00000 n 0000491733 00000 n 0000507901 00000 n 0000507498 00000 n 0000518439 00000 n 0000518098 00000 n 0000521083 00000 n 0000521052 00000 n 0000521191 00000 n 0000521427 00000 n 0000522224 00000 n 0000522320 00000 n 0000522405 00000 n 0000531053 00000 n 0000530736 00000 n 0000551134 00000 n 0000550693 00000 n 0000560720 00000 n 0000560397 00000 n 0000564287 00000 n 0000564407 00000 n 0000564527 00000 n 0000564647 00000 n 0000564769 00000 n 0000564868 00000 n 0000564969 00000 n 0000571817 00000 n 0000576767 00000 n 0000576808 00000 n 0000576848 00000 n 0000576982 00000 n trailer << /Size 1156 /Root 1154 0 R /Info 1155 0 R /ID [<49060AF50D861A117BFBCC19BFE9ACD9> <49060AF50D861A117BFBCC19BFE9ACD9>] >> startxref 577246 %%EOF chuck-1.2.0.8.dfsg/doc/GOTO0000644000175000017500000000017110600421722013576 0ustar piempiem ChucK Documentation + Tutorials: http://chuck.cs.princeton.edu/doc/ ChucK home: http://chuck.cs.princeton.edu/ chuck-1.2.0.8.dfsg/examples/0000755000175000017500000000000010600421722014155 5ustar piempiemchuck-1.2.0.8.dfsg/examples/array/0000755000175000017500000000000010600421722015273 5ustar piempiemchuck-1.2.0.8.dfsg/examples/array/array_argument.ck0000644000175000017500000000050510600421722020632 0ustar piempiem// array pass by reference test - should change values? // function that takes array fun void mirror( int arg[] ) { // assign 0th element to 1st element arg[0] => arg[1]; } // declare array int foo[2]; 2 => foo[0]; 1 => foo[1]; // call the function mirror( foo ); // test if ( foo[0] == foo[1] ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/array/array_assign.ck0000644000175000017500000000027710600421722020302 0ustar piempiem// 17.ck : partial array // declare int array 2x2 int x[2][2]; // assign 2 => x[1][1]; // assign partial array reference to 'y' x[1] @=> int y[]; // test if( y[1] == 2 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/array/array_mdim.ck0000644000175000017500000000052510600421722017740 0ustar piempiem// 15.ck : multi-dimensional array instantiation // delcare int array 2x2x2 int a[2][2][2]; // delcare float array 2x2x2 float b[2][2][2]; // assign 5 => a[1][1][1] => b[1][1][1]; // multi-dimensional array initialization [ [1,2], [3,4] ] @=> int c[][]; // test if( a[1][1][1] == 5 && b[1][1][1] == 5.0 && c[0][1] == 2 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/array/array_storage.ck0000644000175000017500000000022110600421722020447 0ustar piempiem// multi-dimensional array int a[2][2][2]; // assignment 4 => a[0][0][1]; // access a[0][0][1] => int b; // test if ( b == 4 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/array/array_sub_assign.ck0000644000175000017500000000034010600421722021142 0ustar piempiem// multi-dimensional array // array to array assignment int a[2][2][2]; int b[2][2]; // assignment 1 => b[0][1]; 2 => b[0][0]; // assign b to 0th element of a b @=> a[0]; // verify if ( a[0][0][1] == 1 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/basic/0000755000175000017500000000000010600421722015236 5ustar piempiemchuck-1.2.0.8.dfsg/examples/basic/adc.ck0000644000175000017500000000020210600421722016276 0ustar piempiem// mic-in to audio out // the patch adc => dac; // infinite time-loop while( true ) { // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/adsr.ck0000644000175000017500000000071310600421722016507 0ustar piempiem// an ADSR envelope // (also see envelope.ck) SinOsc s => ADSR e => dac; // set a, d, s, and r e.set( 10::ms, 8::ms, .5, 500::ms ); // set gain .5 => s.gain; // infinite time-loop while( true ) { // choose freq Std.rand2( 20, 120 ) => Std.mtof => s.freq; // key on - start attack e.keyOn(); // advance time by 800 ms 500::ms => now; // key off - start release e.keyOff(); // advance time by 800 ms 800::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/alarm.ck0000644000175000017500000000065710600421722016661 0ustar piempiem// how long 2::hour => dur T; // frequency 880 => float f; // remember now => time start; now + T => time later; // wait while( now < later ) { <<< (T - (now - start)) / second, "left..." >>>; 1::second => now; } // patch SinOsc s => JCRev r => dac; .025 => r.mix; f => s.freq; // infinite while loop while( true ) { // go 1.0 => s.gain; 300::ms => now; // stop 0.0 => s.gain; 300::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/args.ck0000644000175000017500000000034610600421722016514 0ustar piempiem// shows getting command line arguments // (example run: chuck args:1:2:foo) // print number of args <<< "number of arguments:", me.args() >>>; // print each for( int i; i < me.args(); i++ ) { <<< " ", me.arg(i) >>>; } chuck-1.2.0.8.dfsg/examples/basic/bar.ck0000644000175000017500000000045110600421722016321 0ustar piempiem// point of attack for random otf demo SinOsc s => dac; .2 => s.gain; // an array: add stuff [ 0 ] @=> int hi[]; while( true ) { // change parameters here Std.mtof( 45 + Std.rand2(0,0) * 12 + hi[Std.rand2(0,hi.cap()-1)] ) => s.freq; // different rate 200::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/blit.ck0000644000175000017500000000054510600421722016513 0ustar piempiem// patch Blit s => JCRev r => dac; .5 => s.gain; .05 => r.mix; // an array [ 0, 2, 4, 7, 9, 11 ] @=> int hi[]; // infinite time loop while( true ) { // frequency Std.mtof( 33 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] ) => s.freq; // harmonics Std.rand2( 1, 5 ) => s.harmonics; // advance time 120::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/blit2.ck0000644000175000017500000000100010600421722016560 0ustar piempiem// patch Blit s => ADSR e => JCRev r => dac; .5 => s.gain; .05 => r.mix; // set adsr e.set( 5::ms, 3::ms, .5, 5::ms ); // an array [ 0, 2, 4, 7, 9, 11 ] @=> int hi[]; // infinite time loop while( true ) { // frequency Std.mtof( 33 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] ) => s.freq; // harmonics Std.rand2( 1, 5 ) => s.harmonics; // key on e.keyOn(); // advance time 120::ms => now; // key off e.keyOff(); // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/chirp.ck0000644000175000017500000000156510600421722016671 0ustar piempiem// po-tweet! // patch SinOsc s => dac; // gain .4 => s.gain; // call chirp chirp( 127, 20, 1::second ); // call chirp (with tinc) chirp( 20, 120, 1.5::second, 100::ms ); // chirp function fun void chirp( float src, float target, dur duration ) { chirp( src, target, duration, 1::ms ); } // chirp function (with tinc) fun void chirp( float src, float target, dur duration, dur tinc ) { // initialize freq src => float freq; // find the number of steps duration / tinc => float steps; // find the inc ( target - src ) / steps => float inc; // counter float count; // do the actual work over time while( count < steps ) { // increment the freq freq + inc => freq; // count 1 +=> count; // set the freq Std.mtof( freq ) => s.freq; // advance time tinc => now; } } chuck-1.2.0.8.dfsg/examples/basic/chirp2.ck0000644000175000017500000000274410600421722016753 0ustar piempiem// more chirping... // patch with envelope and pan SinOsc s => Envelope e => Pan2 p => dac; // gain .5 => s.gain; // pan hard left -1 => p.pan; // call chirp chirp( 127, 20, 1::second ); // wait for envelope to go down 10::ms => now; // pan hard right 1 => p.pan; // call chirp chirp( 20, 120, 1::second, 100::ms ); // wait a second 1::second => now; // randomize pan Std.rand2f( -1, 1 ) => p.pan; // call chirp chirp( 30, 110, .5::second ); // wait for envelope to go down 10::ms => now; // pan Std.rand2f( -1, 1 ) => p.pan; // call chirp chirp( 110, 30, 1::second, 100::ms ); // wait a second 1::second => now; // chirp function fun void chirp( float src, float target, dur duration ) { // just call the other one with default tinc chirp( src, target, duration, 1::ms ); } // chirp function (with tinc) fun void chirp( float src, float target, dur duration, dur tinc ) { // initialize freq src => float freq; // find the number of steps duration / tinc => float steps; // find the inc ( target - src ) / steps => float inc; // counter float count; // set env .01 * duration / second => e.time; // open env 1 => e.keyOn; // do the actual work over time while( count < steps ) { // increment the freq freq + inc => freq; // count 1 +=> count; // set the freq Std.mtof( freq ) => s.freq; // advance time tinc => now; } // close env 1 => e.keyOff; } chuck-1.2.0.8.dfsg/examples/basic/comb.ck0000644000175000017500000000062710600421722016502 0ustar piempiem// a simple comb filter // Ge Wang (gewang@cs.princeton.edu) // feedforward Impulse imp => Gain out => dac; // feedback out => Delay delay => out; // our radius .99999 => float R; // our delay order 500 => float L; // set delay L::samp => delay.delay; // set dissipation factor Math.pow( R, L ) => delay.gain; // fire impulse 1 => imp.next; // advance time (Math.log(.0001) / Math.log(R))::samp => now; chuck-1.2.0.8.dfsg/examples/basic/curly++.ck0000644000175000017500000000073510600421722017046 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe++ larry++ curly++ // impulse to filter to dac SndBuf i => NRev r => dac; // load glottal ooo "special:glot_ooo" => i.read; // play //5.0 => i.rate; .1 => r.mix; 0.0 => float v; // infinite time-loop while( true ) { // set the current sample/impulse 0 => i.pos; // control gain Math.cos(v) => i.gain; // increment v .05 +=> v; // advance time 81.0::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/curly.ck0000644000175000017500000000107610600421722016717 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe larry curly // impulse to filter to dac Impulse i => BiQuad f => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // initialize float variable 0.0 => float v; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // sweep the filter resonant frequency Std.fabs(Math.sin(v)) * 800.0 => f.pfreq; // increment v v + .1 => v; // advance time 101::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/delay.ck0000644000175000017500000000023710600421722016655 0ustar piempiem// patch adc => DelayL delay => dac; // set delay parameters .75::second => delay.max => delay.delay; // infinite time loop while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/demo0.ck0000644000175000017500000000023710600421722016563 0ustar piempiem// demo0.ck // basic demo showing time and duration 5::second + now => time later; while( now < later ) { <<>>; 1::second => now; } <<>>; chuck-1.2.0.8.dfsg/examples/basic/demo1.ck0000644000175000017500000000026110600421722016561 0ustar piempiem// demo1.ck // candidate for most trivial demo 0 => int a => int t; 1 => int b; 15 => int c; while( c > 0 ) { a + b => t; b => a; << b>>>; c - 1 => c; } chuck-1.2.0.8.dfsg/examples/basic/demo2.ck0000644000175000017500000000076210600421722016570 0ustar piempiem// demo2.ck // really lame! // set the global gain .1 => dac.gain; // connect SinOsc a => dac; 110.0 => a.freq; 1::second => now; SinOsc b => dac; 220.0 => b.freq; 1::second => now; SinOsc c => dac; 440.0 => c.freq; 1::second => now; SinOsc d => dac; 880.0 => d.freq; 1::second => now; SinOsc e => dac; 1760.0 => e.freq; 1::second => now; // disconnect a =< dac; 1::second => now; b =< dac; 1::second => now; c =< dac; 1::second => now; d =< dac; 1::second => now; e =< dac; 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/demo3.ck0000644000175000017500000000057710600421722016575 0ustar piempiem// demo3.ck // super lame // global gain Gain g => dac; // set gain .5 => g.gain; 110.0 => float freq; 6 => int x; // loop while( x > 0 ) { // connect to gain SinOsc s => g; // change frequency freq => s.freq; freq * 2.0 => freq; // decrement x 1 -=> x; // advance time by 1 second 1::second => now; // disconnect the sinosc s =< g; } chuck-1.2.0.8.dfsg/examples/basic/echo.ck0000644000175000017500000000043710600421722016477 0ustar piempiem// feedforward adc => Gain g => dac; // feedback g => Gain feedback => DelayL delay => g; // set delay parameters .75::second => delay.max => delay.delay; // set feedback .5 => feedback.gain; // set effects mix .75 => delay.gain; // infinite time loop while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/envelope.ck0000644000175000017500000000066510600421722017401 0ustar piempiem// run white noise through envelope Noise n => Envelope e => dac; // infinite time-loop while( true ) { // random choose rise/fall time Std.rand2f(10,500)::ms => dur t => e.duration; // print <<< "rise/fall:", t/ms, "ms" >>>; // key on - start attack e.keyOn(); // advance time by 800 ms 800::ms => now; // key off - start release e.keyOff(); // advance time by 800 ms 800::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/fm.ck0000644000175000017500000000054610600421722016164 0ustar piempiem// FM synthesis by hand // carrier SinOsc c => dac; // modulator SinOsc m => blackhole; // carrier frequency 220 => float cf; // modulator frequency 550 => float mf => m.freq; // index of modulation 200 => float index; // time-loop while( true ) { // modulate cf + (index * m.last()) => c.freq; // advance time by 1 samp 1::samp => now; } chuck-1.2.0.8.dfsg/examples/basic/fm2.ck0000644000175000017500000000047210600421722016244 0ustar piempiem// FM using sinosc // modulator to carrier SinOsc m => SinOsc c => dac; // carrier frequency 220 => float cf => c.freq; // modulator frequency 550 => m.freq; // index of modulation 200 => m.gain; // phase modulation is FM synthesis (sync is 2) 2 => c.sync; // time-loop while( true ) { 1::second => now; } chuck-1.2.0.8.dfsg/examples/basic/fm3.ck0000644000175000017500000000041610600421722016243 0ustar piempiem// actual FM using sinosc (sync is 0) // modulator to carrier SinOsc m => SinOsc c => dac; // carrier frequency 220 => float cf => c.freq; // modulator frequency 20 => m.freq; // index of modulation 200 => m.gain; // time-loop while( true ) { 1::second => now; } chuck-1.2.0.8.dfsg/examples/basic/foo.ck0000644000175000017500000000044710600421722016345 0ustar piempiem// hello everyone. // a chuck is born... // its first words: SinOsc s => JCRev r => dac; .2 => s.gain; .1 => r.mix; // an array [ 0, 2, 4, 7, 9, 11 ] @=> int hi[]; while( true ) { Std.mtof( 45 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] ) => s.freq; 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/foo2.ck0000644000175000017500000000117410600421722016425 0ustar piempiem// bandlimited ugens (Blit, BlitSaw, BlitSquare) Blit s => Pan2 p; p.left => JCRev r1 => dac.left; p.right => JCRev r2 => dac.right; // initial settings .5 => s.gain; .1 => r1.mix; .1 => r2.mix; // an array [ 0, 2, 4, 7, 9, 11 ] @=> int hi[]; // set the harmonic 4 => s.harmonics; // spork the pan control spork ~ dopan(); // infinite time loop while( true ) { Std.mtof( 33 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] ) => s.freq; 120::ms => now; } // pan control fun void dopan() { float t; while( true ) { .7 * Math.sin(t) => p.pan; .005 +=> t; 10::ms => now; } } chuck-1.2.0.8.dfsg/examples/basic/func.ck0000644000175000017500000000063610600421722016515 0ustar piempiem8 => int a; fun int abs( int v ) { if( v < 0 ) return -v; return v; } fun void args( int y, int b ) { 4 => a; <<>>; } fun float sum( float a, float b ) { return a + b; } fun void go( int a ) { <<>>; if( a == 0 ) return; go( abs(a)-1 ); } int i; for( 0 => i; i < 10; i + 1 => i ) go( 1000 ); <<>>; args( 1, 2 ); <<>>; <<>>; chuck-1.2.0.8.dfsg/examples/basic/i-robot.ck0000644000175000017500000000047210600421722017133 0ustar piempiem// take me to your leader (talk into the mic) // gewang, prc // our patch - feedforward part adc => Gain g => DelayL d => dac; adc => Gain g2 => dac; // feedback d => Gain g3 => d; // set parameters 15::ms => d.delay; 0.05 => g.gain; 0.05 => g2.gain; 0.95 => g3.gain; // time loop while( true ) 100::ms => now; chuck-1.2.0.8.dfsg/examples/basic/imp.ck0000644000175000017500000000045710600421722016350 0ustar piempiem// impulse generator is cool... // this demo is not // connect impulse generator Impulse i => dac; .5 => i.gain; // emit impulse every so often 2000 => int a; while( 1 ) { // set the next sample 1.0 => i.next; // advance time a::samp => now; a - 8 => a; if( a <= 0 ) 2000 => a; } chuck-1.2.0.8.dfsg/examples/basic/infnan.ck0000644000175000017500000000041010600421722017021 0ustar piempiem// big number 1000000000000000000000000000.0 => float n; // overflow it repeat( 20 ) n *=> n; // test it <<< Math.isinf( n ) >>>; // bye sanity 0 *=> n; // test it <<< Math.isnan( n ) >>>; // more <<< 1.0 / 0.0 => Math.isinf >>>; <<< 0.0 / 0.0 => Math.isnan >>>; chuck-1.2.0.8.dfsg/examples/basic/larry++.ck0000644000175000017500000000203710600421722017036 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe++ larry++ curly++ // impulse to filter to dac SndBuf i => BiQuad f => Gain g => JCRev r => dac; // second formant i => BiQuad f2 => g; // third formant i => BiQuad f3 => g; // set the filter's pole radius 0.800 => f.prad; .995 => f2.prad; .995 => f3.prad; // set equal gain zeroes 1 => f.eqzs; 1 => f2.eqzs; 1 => f3.eqzs; // initialize float variable 0.0 => float v => float v2; // set filter gain .1 => f.gain; .1 => f2.gain; .01 => f3.gain; 0.05 => r.mix; // load glottal pop "special:glot_pop" => i.read; // play 1.0 => i.rate; // infinite time-loop while( true ) { // set the current sample/impulse 0 => i.pos; // sweep the filter resonant frequency 250.0 + Math.sin(v*100.0)*20.0 => v2 => f.pfreq; 2290.0 + Math.sin(v*200.0)*50.0 => f2.pfreq; 3010.0 + Math.sin(v*300.0)*80.0 => f3.pfreq; // increment v v + .05 => v; // gain 0.2 + Math.sin(v)*.1 => g.gain; // advance time (1000.0 + Std.rand2f(-100.0, 100.0))::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/larry.ck0000644000175000017500000000107510600421722016711 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe larry curly // impulse to filter to dac Impulse i => BiQuad f => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // initialize float variable 0.0 => float v; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // sweep the filter resonant frequency Std.fabs(Math.sin(v)) * 4000.0 => f.pfreq; // increment v v + .1 => v; // advance time 99::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/lfo.ck0000644000175000017500000000031310600421722016332 0ustar piempiem// using SinOsc.period (alternative to .freq) // sinosc SinOsc lfo => dac; // set period 1::second => lfo.period; // infinite time loop while( true ) { <<< lfo.last(), "" >>>; 50::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/moe++.ck0000644000175000017500000000173710600421722016473 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe++ larry++ curly++ // source to filter to dac SndBuf i => BiQuad f => Gain g => dac; // second formant i => BiQuad f2 => g; // third formant i => BiQuad f3 => g; // set the filter's pole radius .995 => f.prad; .995 => f2.prad; .995 => f3.prad; // set equal gain zeros 1 => f.eqzs; 1 => f2.eqzs; 1 => f3.eqzs; // initialize float variable 1.5 * 3.14 => float v; // set filter gain .2 => f.gain; .04 => f2.gain; .01 => f3.gain; // load glottal pop "special:glot_pop" => i.read; // play 1.0 => i.rate; // infinite time-loop while( true ) { // set the current pos 0 => i.pos; // sweep the filter resonant frequency 660.0 + Math.sin(v)*80.0 => f.pfreq; 1780.0 + Math.sin(v*.5)*50.0 => f2.pfreq; 2410.0 + Math.sin(v*.25)*150.0 => f3.pfreq; // increment v v + .05 => v; // gain 0.2 + Math.sin(v)*.2 => g.gain; // advance time (80.0 + Math.sin(v*2.0)*10.0)::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/moe.ck0000644000175000017500000000107610600421722016341 0ustar piempiem// run each stooge, or run three stooges concurrently // %> chuck moe larry curly // impulse to filter to dac Impulse i => BiQuad f => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // initialize float variable 0.0 => float v; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // sweep the filter resonant frequency Std.fabs(Math.sin(v)) * 4000.0 => f.pfreq; // increment v v + .1 => v; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/rec-auto.ck0000644000175000017500000000135210600421722017275 0ustar piempiem// chuck this with other shreds to record to file // example> chuck foo.ck bar.ck rec (see also rec2.ck) // pull samples from the dac dac => Gain g => WvOut w => blackhole; // set the prefix, which will prepended to the filename // do this if you want the file to appear automatically // in another directory. if this isn't set, the file // should appear in the directory you run chuck from // with only the date and time. "chuck-session" => w.autoPrefix; // this is the output file name "special:auto" => w.wavFilename; // print it out <<<"writing to file: ", w.filename()>>>; // any gain you want for the output .5 => g.gain; // infinite time loop... // ctrl-c will stop it, or modify to desired duration while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/rec.ck0000644000175000017500000000107710600421722016333 0ustar piempiem// chuck this with other shreds to record to file // example> chuck foo.ck bar.ck rec (see also rec2.ck) // arguments: rec: // get name me.getArg(0) => string filename; if( filename.length() == 0 ) "foo.wav" => filename; // pull samples from the dac dac => Gain g => WvOut w => blackhole; // this is the output file name filename => w.wavFilename; <<<"writing to file:", "'" + w.filename() + "'">>>; // any gain you want for the output .5 => g.gain; // infinite time loop... // ctrl-c will stop it, or modify to desired duration while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/ring.ck0000644000175000017500000000072510600421722016520 0ustar piempiem//-------------------------------------------- // simple ring modulation // // any ugen has .op: // --- // -1 pass through the input // 0 stop input // 1 add inputs (default) // 2 subtract from first input // 3 multiply inputs // 4 divide from first input //-------------------------------------------- // the patch adc => Gain g => dac; SinOsc s => g; // multiply inputs at g 3 => g.op; // presets 400.0 => s.freq; // time loop while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/basic/sndbuf.ck0000644000175000017500000000046310600421722017041 0ustar piempiem// sound file "../data/snare.wav" => string filename; if( me.args() ) me.arg(0) => filename; // the patch SndBuf buf => dac; // load the file filename => buf.read; // time loop while( true ) { 0 => buf.pos; Std.rand2f(.2,.9) => buf.gain; Std.rand2f(.5,1.5) => buf.rate; 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/step.ck0000644000175000017500000000025410600421722016531 0ustar piempiem// step gen to dac Step s => dac; .5 => float v; // infinite time-loop while( 1 ) { // advance time 1::ms => now; // set value v => s.next; -v => v; } chuck-1.2.0.8.dfsg/examples/basic/tick.ck0000644000175000017500000000023110600421722016503 0ustar piempiem// tick tock // infinite time loop while( true ) { // print now in seconds <<< "tick:", (now / second), "seconds" >>>; 1::second => now; } chuck-1.2.0.8.dfsg/examples/basic/tick2.ck0000644000175000017500000000035310600421722016572 0ustar piempiem// tick tock // wait until the start of the next second second - (now % second) => now; // infinite time loop while( true ) { // print now in seconds <<< "tick:", (now / second) $ int, "seconds" >>>; 1::second => now; } chuck-1.2.0.8.dfsg/examples/basic/unchuck.ck0000644000175000017500000000136010600421722017215 0ustar piempiem// noise generator, biquad filter, dac (audio output) Noise n => BiQuad f => dac; // set biquad pole radius .99 => f.prad; // set biquad gain .025 => f.gain; // set equal zeros 1 => f.eqzs; // our float 0.0 => float t; 3::second + now => time later; // time-loop while( now < later ) { // sweep the filter resonant frequency 100.0 + Std.fabs(Math.sin(t)) * 1000.0 => f.pfreq; t + .05 => t; // advance time 100::ms => now; } // unlink the ugen f from dac f =< dac; // let more time pass 3::second => now; // relink f => dac; // time-loop 3::second + now => later; while( now < later ) { // resume sweep 100.0 + Std.fabs(Math.sin(t)) * 1000.0 => f.pfreq; t + .05 => t; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/valueat.ck0000644000175000017500000000072110600421722017216 0ustar piempiem// (see sndbuf.ck or otf_01.ck for non-insane usage of sndbuf) SndBuf buf; "../data/kick.wav" => buf.read; // the patch (no sndbuf involved) Impulse i => dac; // infinite time-loop while( true ) { // index int pos; // repeat this many times repeat( buf.samples() ) { // set next sample buf.valueAt( pos ) => i.next; // increment index pos++; // advance time by one samp 1::samp => now; } } chuck-1.2.0.8.dfsg/examples/basic/whirl.ck0000644000175000017500000000043410600421722016703 0ustar piempiem// sine to dac SinOsc s => dac; // let's turn down gain, for this can be loud and annoying .1 => s.gain; // infinite time loop 0.0 => float t; while( true ) { // modulate ( Math.sin(t) + 1.0 ) * 10000.0 => s.sfreq; t + .004 => t; // advance time 1::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/whole.ck0000644000175000017500000000073010600421722016673 0ustar piempiem// another candidate for lamest demo // patch SinOsc s => JCRev r => dac; .5 => r.gain; .075 => r.mix; // note number 20 => float note; // go up to 127 while( note < 128 ) { // convert MIDI note to hz Std.mtof( note ) => s.freq; // turn down the volume gradually .5 - (note/256.0) => s.gain; // move up by whole step note + 2 => note; // advance time .125::second => now; } // turn off s 0 => s.gain; // wait a bit 2::second => now; chuck-1.2.0.8.dfsg/examples/basic/wind.ck0000644000175000017500000000064110600421722016517 0ustar piempiem// noise generator, biquad filter, dac (audio output) Noise n => BiQuad f => dac; // set biquad pole radius .99 => f.prad; // set biquad gain .05 => f.gain; // set equal zeros 1 => f.eqzs; // our float 0.0 => float t; // infinite time-loop while( true ) { // sweep the filter resonant frequency 100.0 + Std.fabs(Math.sin(t)) * 1000.0 => f.pfreq; t + .01 => t; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/wind2.ck0000644000175000017500000000131210600421722016575 0ustar piempiem// noise generator, biquad filter, dac (audio output) Noise n => BiQuad f => dac; // set biquad pole radius .99 => f.prad; // set biquad gain .05 => f.gain; // set equal zeros 1 => f.eqzs; // our float 0.0 => float t; // concurrent control fun void wind_gain( ) { 0.0 => float g; // time loop to ramp up the gain / oscillate while( true ) { Std.fabs( Math.sin( g ) ) => n.gain; g + .001 => g; 10::ms => now; } } // run wind_gain on anothre shred spork ~ wind_gain(); // infinite time-loop while( true ) { // sweep the filter resonant frequency 100.0 + Std.fabs(Math.sin(t)) * 1000.0 => f.pfreq; t + .01 => t; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/basic/zerox.ck0000644000175000017500000000037210600421722016726 0ustar piempiem// step generator, zero crossing detector, dac Step s => ZeroX z => dac; 1.0 => float v; // infnite time-loop while( true ) { // set the step value v => s.next; // change step value -v => v; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/class/0000755000175000017500000000000010600421722015262 5ustar piempiemchuck-1.2.0.8.dfsg/examples/class/dinky.ck0000644000175000017500000000221110600421722016713 0ustar piempiem// this class defines the Dinky instrument // the variables defined at class level are member variables // // to test this: // > chuck dinky.ck try.ck // // NOTE: in a future version of chuck... // this class will be able to extend UGen // the Dinky class public class Dinky { // impulse to filter to dac Impulse i => BiQuad f => Envelope e; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // set filter gain .2 => f.gain; // set the envelope .001::second => e.duration; public void radius( float rad ) { rad => f.prad; } public void gain( float g ) { g => i.gain; } public void connect( UGen ugen ) { e => ugen; } // t is for trigger public void t( float freq ) { // set the current sample/impulse 1.0 => i.next; // set filter resonant frequency freq => f.pfreq; // open the envelope e.keyOn(); } // t is for trigger (using MIDI notes) public void t( int note ) { t( Std.mtof( note ) ); } // another lazy name: c (for close) public void c() { e.keyOff(); } } chuck-1.2.0.8.dfsg/examples/class/try.ck0000644000175000017500000000216510600421722016423 0ustar piempiem// uses the Dinky class // (run dinky.ck before running this, for now...) // // > chuck dinky try // // NOTE: in a future version of chuck... // 1. we will have better dependency/include system // 2. we can extend Dinky from UGen, so we don't have // to use a 'connect( UGen )' function in Dinky // instantiate a Dinky (not connected yet) Dinky imp; // connect the rest of the patch Gain g => NRev r => Echo e => Echo e2 => dac; // direct/dry g => dac; e => dac; // set up delay, gain, and mix 1500::ms => e.max => e.delay; 3000::ms => e2.max => e2.delay; 1 => g.gain; .5 => e.gain; .25 => e.gain; .1 => r.mix; // connect the Dinky // (in a future version of chuck, Dinky can be defined as an UGen) imp.connect( g ); // set the radius (should never be more than 1) imp.radius( .999 ); // an array (our scale) [ 0, 2, 4, 7, 9, 11 ] @=> int hi[]; // infinite time-loop while( true ) { // trigger 45 + Std.rand2(0,3) * 12 + hi[Std.rand2(0,hi.cap()-1)] => imp.t; // let time pass 195::ms => now; // close the envelope imp.c(); // let a bit more time pass 5::ms => now; } chuck-1.2.0.8.dfsg/examples/ctrl/0000755000175000017500000000000010600421722015121 5ustar piempiemchuck-1.2.0.8.dfsg/examples/ctrl/ctrl_break.ck0000644000175000017500000000021210600421722017543 0ustar piempiem// break; 0 => int j; // loop while ( true ) { if ( j >= 5 ) break; 1 +=> j; } // test if ( j == 5 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_break_nested.ck0000644000175000017500000000044010600421722021110 0ustar piempiem// break in nested block 0 => int j; 0 => int i; // loop while ( j < 5 ) { while ( i < 10 ) { 1 +=> i; // arbitrary break here, shouldn't bust of out the outer loop if ( i > 5 ) break; } 1 +=> j; } // test if ( j == 5 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_continue.ck0000644000175000017500000000074110600421722020312 0ustar piempiem// continue in nested block 0 => int j; 0 => int i; 0 => int check; // loop while ( j < 5 ) { 0 => i; while ( i < 5 ) { 1 +=> i; if ( j < 4 ) continue; // because of continue, this only happens in last ( j==0 ) 2 +=> check; } // if continue malfunctions, this is skipped, and we get INFINITE LOOP 1 +=> j; } // make sure that continue does the right thing in the inner loop? if ( check == 10 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_do_until.ck0000644000175000017500000000020210600421722020273 0ustar piempiem// do-until 0 => int j; 0 => int i; do { 1 +=> j; 1 +=> i; } until ( i >= 5 ); // test if ( j == 5 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_for_loop.ck0000644000175000017500000000043510600421722020305 0ustar piempiem// for loop ( factorial ) , -=>, *=> // function fun int factorial ( int arg ) { 1 => int r; arg => int b; for ( b ; b > 1 ; 1 -=> b ) { b *=> r; } return r; } // call the function factorial ( 4 ) => int x; // test if ( x == 24 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_sequencer.ck0000644000175000017500000000517210600421722020463 0ustar piempiem// um, by philipd // (what is it?) class Player { UGen @ base; fun void connect( UGen target ) { base => target; } fun void noteOn ( float note, float vel ) {} fun void noteOff ( float vel ) {} } class Note { float note; float vel; dur length; fun void set ( float nt, float vl, dur ln ) { nt => note; vl => vel; ln => length; } fun void playOn ( Player p) { if ( note > 0 ) { p.noteOn( note , vel ); } } fun void playOnAlt( Player p, float noff, float vmul ) { p.noteOn( note+noff, vel*vmul ); } } class MandPlayer extends Player { Mandolin m @=> base; fun void noteOn ( float note, float vel ) { Std.mtof ( note ) => m.freq; vel => m.pluck; } } class FlutePlayer extends Player { PercFlut f @=> base; fun void noteOn ( float note, float vel ) { Std.mtof ( note ) => f.freq; vel => f.noteOn; } } class ClarPlayer extends Player { Clarinet c @=> base; fun void noteOn ( float note, float vel ) { Std.mtof ( note ) => c.freq; vel => c.startBlowing; } fun void noteOff ( float vel ) { vel => c.stopBlowing; } } 12 => int seqn; Note sequence[seqn]; int order[seqn]; [0,2,4,7,9, 12, 14, 16, 19, 21] @=> int scale[]; 10 => int nscale; [0.25::second, 0.125::second, 0.125::second, 0.375::second] @=> dur times[]; 4 => int ntimes; //fun initialize ( Note sequence, int n ) { fun void newsequence() { for ( 0 => int i; i < seqn ; i++ ) { i => order[i]; 55 + scale[Std.rand2(0, nscale - 1)] => int note; times[Std.rand2(0, ntimes - 1)] => dur mydur; Std.rand2f( 0.75, 0.9 ) => float vel; sequence[i].set( note, vel, mydur ); } } fun void swap( ) { Std.rand2(0,seqn-1) => int a; ( a + Std.rand2(1,seqn-1) ) % seqn => int b; order[a] => int tmp; order[b] => order[a]; tmp => order[a]; } MandPlayer mand; ClarPlayer clar; Gain g => JCRev j => Echo e => dac; 0.95 => j.gain; 0.2 => j.mix; 1.15::second => e.max; 1.0::second => e.delay; 0.3 => e.mix; mand.connect(g); clar.connect(g); 0.6 => g.gain; newsequence(); while ( true ) { for ( 0 => int j ; j < seqn; j++ ) { sequence[order[j]] @=> Note cur; cur.playOn ( mand ); cur.playOnAlt ( clar, 12 , 0.7 ); 2.0 * cur.length => now; cur.playOnAlt( mand, 7, 0.33); cur.length => now; } for ( Std.rand2(0,2) => int j ; j > 0 ; j-- ) swap(); if ( Std.rand2(0, 10) > 8 ) newsequence(); } chuck-1.2.0.8.dfsg/examples/ctrl/ctrl_until.ck0000644000175000017500000000021310600421722017613 0ustar piempiem// until ( v2 ) 0 => int j; 0 => int i; // loop until ( i == 5 ) { 1 +=> j; 1 +=> i; } // test if ( j == 5 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/data/0000755000175000017500000000000010600421722015066 5ustar piempiemchuck-1.2.0.8.dfsg/examples/data/hihat-open.wav0000644000175000017500000010655210600421722017652 0ustar piempiemRIFFbWAVEfmt DXdataO)DNic1N hr" ;6' z*F˴9 ,N(2. a ,;,\13M߫GSϑ;X$78Mz%aZV2^M0ݡ.v6ꞋFNpϝ"R!0#y٫#JcZ8 vަ"Ԝ- n4KI{ 5M5h6jPenÛ5Q7`M>eb;+A v5{ 9J(2ayY5h&m# C+J*}<Ū :Ė G=czH*C")F&2f/;'{ڠБ. ]nN4r?$rK6uL]or'7ѷW>8!f $1h 132 K_)(/K.U>}6H gQ"Վ.>C>x@#|n~>-dj GS)h<U܌U- WT1 Y8 G"m e~B/2!&J  S %"=Nn-ܣ2!3+R!YaC8tI=F sCP(/ wpMQ y7^0A @0dAO%u` %Io#=&5ԭzQ(x#N P 3 B=^"_ j-CMzL06 )H0o>'t0d40jF + {5` -+,G f2R#- 6z1hf\+3 q  5 ,?ӹK" j!PCEңۋ\ZՊ)-By ۃ t} Zc=9w'9 v)@ k7'>pۛ5*O$[о*1(T.>h+ z $`Y9 ߶.#rK +Hd@_9, #!̃"oztZp a0%!RR Da% 84"J:p L }Q>A. !f[ bG{ "H k o X)12r g@s(J4Z] zLN oo& . 2h$ݥ)JMoc+.ͺ2<#U$cO> ۬"FHuW;Y6Vf%"c :n=( ҹ/5.7xN}=| e! L wU( n9VYǺ ߰;.rkgu]+aH!9E}"`M3ߎB  p݇}{߫ _ n( d)]$['G~Zz8 DgN"* Y G!&d-Y 2&g]&G!@FH,#-O(6ec.M @ *!=2Vl31!I45$uA  ?" e Y>%0 "( NtO$C>/,m@6Ha" >%*D3&ܠ8""iQ "_u`"U $#!U5 =8 "B>w{ "5rȼ/r s1.if DL!VC W!;r "XB &z?1 $p  \/ |+ޮ.0; n2=Ԫ),z!< !I= X9J.nV;-uNQ&=&|G_o/#K= %6 BJXG9  c SU`8xXkPU&y +B"f- @j9Nu 'V (jjC BN?;@K ^ح ; >+n M>!.T (/`e_ TE"Xcu'Xmky;# Y QWb%p?7&c G p:[q4t!(x܂mb EZG9JNY!Y6[8 I! (֮gr%\wsp&Q mdi+rY'"@ cDf E & je .@fe M l W5 f( u i <a]9 Q<"%$Q ==!\ [p48 m`S!~8ljN",u%uݕ ~" TIÂ%  N` i $% Hj~ IݜG> e6 rز:$ EwU#"IC E  ָy 2G!:%5͗&/k&e(r*zu۬h XY 0~{ ~' ? +Uנx?Pa P+[NSu ,KXzLܫ=V c!JF` ^ U4 n.i2Y h!IC+ P % 5 8bU{5`9f%&0 u[ |hEK!_ hH6 ~ .C 7 2&ג bd P ;CME$6#"R~{^&~`7 1<_Se' ؁3&X kC &Jp CQ % _JxM ݩfv06b'HV@' dl ` Bv_u g2` #d &70I>)bM g8 E0*N^[F 1 Y- 7# nBvPB xM@6]P "a "$ !G I 7EmRܕ F 9 Thg>{ ͙q  Lr+ x5 [20 %f  nE=WmKK yVr 9JR{ $&i>kt. V+r( Lv SҘ_ y2/E S ~};HiE ?Fn)Xe , 5u&xo/r  qi c ( :f P77bU]PuePq0 @tE - Vx = 1 2H & 0%  'R`F =DY<"  nDM2 1F@M VP%AB zv60  EZ?mr +h *u@U/f  ߮ *Mih$ uP C g#2+wEK  +*m6{V u Vv&/08[ i  s@cz0e$ -:o 3(6N=@J<( -)hF mh!NcK=2 ./"h   b %v\m D]~  i3 Ex c ^cYH )2CRN z/%:!nk ]O , M4N S A`6N 5} 3vg%v O# ;| ' L Ij2D`E EG} -tJXV JSs) 4 0 X ;` # ^%1d08`f ;x@/ij1 az +WS5%E`y2 h C}o [9ns:nڬ|+:K RpSm;*' {9D{E tXM =h/M V~`~%M @&Zfwp WY{ Xz0,2@F gAJ@o~ P `MBF[~ =^ G1 % [&-r :25 nP boRK  }B]2 V; 1{\7^ ` n W 06 8NS :F1;ZzlfUk(/  cDC2uV 8 E.OK;< y bsPeslEU| 2F0z  514h#v +_mk :6{E"=B w=1H,F xM P-d ! 85;sR0VC (; 2"}? 2$`? tC ' :{  L(0"" p$+XQmYfS r#"M"`3Q w@PU-* m  cM e k 2 . 6Q] 6:.HHL .?dg_+ a cP[ 5) 8Dx z q@528x+SP58S `G $EUd]7 i6+#@ibS->cVxjpC0#  @=?2@ i @>   E[. %2  1} ] 1 bs8v0 JV ";w/ gJC j0&JG]#.z %iYn pJkn B 6  b@ % > . [WX |` Y%9B9 = J E\ /RJt 5@`HF2O?-1 cK(5$߇& =zPc /rw;U0~ E> HC&UCEAe6e $wzK0%M hs`F c YE05 n@Pi k K X cE9gx gNx ~| F)B!%%Red:+2 [ 9 x A + 9p sf R m !,^m Fu" d9 kX V5 6= >r`H fB8 +6` 8[^U *B 0daxh   M8?- Xv5pa(~?uC [:: n "?p b[ B 6]U:\=g_j8j 5&= S'i; " Cxf"@P %3`; **p)S R  lPMv`hBu +Ec ex{3%-!r; P|23[ER. c2 A k6x+ ` mmZwx3t"pT  EM8u(u6[@e+X mi1x9 ^2 r7 V 7[kS 7h l8& S= 2+ _^9 Z}E_eN+S m8 k&kMSC ( U+s@,!g}^j iN*x[ } Vq`YO,P:ma`~ s\ c eUXS|K[EpB !* gR" cXI(6o- WKnz @[ `K  E#B AJ .7 CYuF8 +lgp 5m= P%. meQPZ L6 2S/WIH 8nl ^JNBt `   BE$ ^1GXAk+8THE{+E] m  Eh~m ~`cs >zBR }3u* 6 n B3 *6T SE5pC)@5"Z Jn.ZM= 5+)7&u u.  ^-%9 >u 6f\8"~ZCPf=h"!8 `6 e= {,x+ gp c 2P fC>+`t SR 7 V uMmhCP ksn u8.rF X@HzDeFkRo!Xp`_N? %PN Hx; [[ uP V;d'IGBe?(*^";a2zu" <(3 }. Po|K-. C9M+a} B3 C/"Njtp%M5 9 B. R7}m%* p3X19=I S>s  %0d; p>! 0kkWQx 6<vc5 kxH  Pu EIk NK h" ^J>%G MT|7VH :\ G#  ``B8 ,;N BU 9ZZ<y S jX :nb" x=> m%@ '5P =-~-x;-g"CJY Z+-38ZN R 5 P#n6`PVjX? Exb0kP4j  A[n2 5  Z*H?Ae  3 S#  :`"S =52P^Ri}> g}!5P}(O= TNv0= 9Y2c "|; it83[}  {x P xRmL K8C xJN +VX9 H| |K+hc= z9m%@p^ #?h U_Pc3 8k P;J8> v emdJ< - z8}~v]N swU"J `US@ J& 0 "Xsm"7 =if{hhe%0O2+ [@K9!I[C cE ( _M=`Jh m_ $ c[:Kc &9 " F@ 0ENe<xNP@Vp#EX#x Cj8^ m1 ~(8^hf"8;+!L   C6zarmZ |m+> Nxm5v ;(hn PA2m}# 5ehq?Lx uj[(<SPzsI9 +jWh u-m(}@cpZhi% z h. (sV9^!9s0S 20 xw ;vr 79J>%"cah JU`=`~!K3v > ws_u /e}]z. ""vJ'~cji@' 2f~j+fv8 P P]9 -~8. hL`x5% }X-2 oTPPn ]V^ yzP=`v(y- c%6 xEZ~ 8 3"5Hc5`zH 5(@z @@2 k(fUJz?p-V KZ=SU'9"bV r8ZF` U `"Pv nFLJ{E?  @x}#K0 E@p3Q t8#(] X =9 (`F~JH h>uhH mA 0k B#k HX u"R ' #o('h~S ^1  ]EV6^$ UZ# Zh /=. = @,pU.3 p qye *q. @ !}C ~0 2/KM5`d%~X A k <3 #]F 6` JmrR^;`-=O(- ;cc" vs=p&h h8 u@J}d" p( (M TP,!=`PAp;+kpM>IFV+ g [u MKf E+ vJ0X w]#EBz:+wc52x> %=E*LR> `;  zxa ~u%6 sN'V>C(.j> e#W<8 [R~ZXwg5U 1}^ z5h`c U7 62 2 W-ZUK( xbd @- 2#fU";I8 hX{;*= (T0.bA|}0 _p%Sx('%~v7 %#f y'z-Jfv0m "* 0(zc 0-FXm N @>BHu5  <0'{ @'8+R ` XJ%0|YH8-"jtx(X+H##%KEUosR3quzh@x NHG7PpKk%E&%J|TEH v>c55\ ~ zs[ XL`P}:mJox @8:(E%Ui2F]'m<| Tz {xeM V ,N?j5 zI51C AE~ Eu/ z2}NX-hNCSE}PeT {7]2KvUq.p OYhP"Vpyx2 ,5`Zm7g8kgA,R Ep .S;SvZNj5 6U *3a ,F(C`. Y f[T S# + ^P+{ 3jJv3% v18^+h`'tVW+"`fheMf^ +mJjt-m2a M `+~P>jO( Fug,2u0xC-SC "/b(hn==:X@e UyzEpx2~-@- GJeXJXhc+z=qVJ-%nv}22R mN Eu8 VK#9<5pBE_ [(vU~Zn_<-0 hE F^(}I;T s}z7@z &u! jhs;vX NE^"-  IXmdv%m}MZ{5+ #0  LH~3 (dZo+eCZ5Nk+ 0 KI bU6BZJ 7UJF0@5j"T[(hcMm+. e}keRB' 2GZZPni8B U@9@SkS% ~0H08(pU''cU M#wPh>99M@sIP"=xxJ-+%h20x ~ VM KP` ;Cv#;(VEu<z=^R;!/=&{NS -v}!>+2.6ip B[c>5u8-'3Kz {5P585 ~;`e-J`Mfs=M; qh`F#X#CiJ"Kk;?9`%=cM[H,>K(8PePC J|R`JCzEKUE E`6-"Ex#+Zm^K"O eG#T F=> ](ZZ}1_@e/m'Uuse uX[@  "~ &= W8q2PIE( H:<b'p&+ wv9SNethC@cY%+]Bn6~Lv s> 2`Vu dtJ  ck'Rx.`"n# JxHM EsR5jqS}` hA{P@ F@ `0zkJ %298RK}u/SCekab]w>em0+wZ. z{mdX%>j2'e  . =2Pv Csv +=s%P9/+ys5}z .KeM-2Xke pEz_k&V`Pie S~9U2~'I B6+v-cU}&c5II+0=h}E81^bE0 0Wmh~ P8"E6;f~'K ~p+A<8# "E+x'I (m j~#J -9O[rTHc;K+I H0NLj2q<5;Cw:2Tsh' z0UZK8"XA6Jp^u5(M5n"j3 05ne`N2>6kiX 0<JH@'^e5; ^[m >mpE*H0xN85hheUhs<n2Eb+mm(p-Zz@KHe/B^R@H7[8 NKc!tv#Z;aZ+n>@x>^0f2J^qs@P(0V,[fKOu"7CEJB'N0BN25@h}N&{r %u(hmb@qK'rN:;Ls1]Z=c&}.[e"sC x(^V'jc&h `XF%EpX6z>`@Z'cF&uR= ~@c[cKU=PU m}>sX-XhE[@m9ZI+/NxnPccmx~XE_P-@tOTK6&X{Esx@m`Ec+Z xf> _'88[m !6jc  ]S; `+mi7 mP:NcHMcN(+uwSq(oVhmA :@B _Y=%x588C`Mz8NUmHm" cU{0zIz{Pi`FmXh"L+uhP@ @-o[%}mXX5&26R Gw67  .tq WU|m <cpX9Ru0qWcA6'+"w-[E8xx(-PP@t [ 3 a X^!E']XS8^;29m0!o{-8sczzTF#LX% ZgsK~5hu+Zz(mZ[50+0Cz PhNNcMn-zs&(X``C hn?2 8v;0 8HZ ss(`="`m0d@8[td0cI9[72+[j BC =C,z<x^zA. c,7P}<#nv9k `@ejP`00U%`~[o}%?Fx5S^2=#z-xh0zYSEp KPZ2s<9+~]p;-=&}R+B"> UN chiXa2f+@'++-JPm @=qCjZMHS3b0E9+zps'JuxE8@v6RhH2F0"#U@'w*b` PI>K2hjC?sy_  `nh25m2u(J K`+qW;%^<EXXI vmCeu9JZ(00cm~|+|0eW-G+c %ue<P sK@8pc`tNJuGUzeztnC5 c^+0 t"bI%6{vXZq"5ReN``n(.?Sjp-(<"~JM8eU"(!|X"!;NhT@|`^/~-Uu7`>c, ej"sN;u_HE53q`;8K@+C3:{w}=ZjU6[Nn/hR5'Z8@05`nuB`OTm5&eP_]PWUKh'hy0z`=h(8@|sp ~JKvX5h[*hGj~It-r#Z@@S `E~q E KZo!YvdR0Uz+JjS;e[2/cw2?S(U?[ON t@# =E7U~'8|pU58`?6F`e#M 5'^Nt 'GNCzZ"C0h :8GF<!:&SZ|U(8T; G=s~pSO^n zScE2&q^t7h;e~esmvhL ^cx2pRp;=08Ts_+]|>`u`Z0+EPJ`csL^zN-+LT ( U95@sh+6nBKX  XJ}- mTm#ZCzE <t`(+`Uv9Ps|879-zj^@(T!Zs=pR( @-L,XjGRBR L2~C@yVj=E#"Nc[Uvu2NWp+SX2Z+u8;@`mnVzT"Y00@bsJ^++`@Bv5z_0E"C@!@U0v0+;N#X }^uN :Ue^}7_ ePuE@_N{UUS@5cJi~<,jm|T+Y[K>IR0^+  +C<~L#zTh"n|`;}YvCL`2B^'R<+0uh K3 ~@8h#q{=J<<e UeX(<`@XNIsc5}8 <B^cq06s(NWeEj>s[#=`S[&v2[8UP-- s`0|=cZs'+m@OBu9pp(E-REx'RW7BF95e 9P-}5;Z"qse`^|j="`ZB2z|c ^me7J8q<GZ#Shz-RmoPNWC~E~Nsn"%N+-0`[6mJjqWr}^5BTv+"NjvO =50<pXW Fxh!KRSJ | (p%Nxaz_@eBe6>=XJ;R&c(2T=LRP+j"Iez+ hcoB=-C ^nL'Z_KzK"[Y c-tukK&uCNZ2#s8s VqU}c5~m=WXRzm6NT9u 2X1~> X+0 ^IWhKj55WCtNsFjnZXz2E97 "xGm S0ccB}R20Wc=WR[ Ru+'jNP2L|#mN59C ` j+L=(on#@IjB&@;c;BXuj% ~ye e8~We -Lx%ceX `B@2(9Bes'>P-+9z^8%5>vPsJU55L+]'UG CG e #> +WG>BsEjcX0u |8X- ^|(R pC+(Imo(}+q+Y'zm8%@ `e'hj2Wj2|GW-ve< 2q"cu-cW`phWGSu#uhRh+L2>cBB(5@}JYq^8(^~0L[z}Y00sPcn-v-P%^ecj8eImt(<x@=jcucS0Wm@n`>`h}--hzPJjj@5 `#||0-^0S#+#BW Sm&+ZC(pWR -e#u^-CG[#pj9jG`G|-X[j9X#%v`h-W2u>`2+^R+eXc#-NEm#+jNx-|c'n8Lmpzece-Tjp(^>78c2z9'nR8#ZG7Nc^8G[=hS-8e8S-h +`SRR  N[<m@q<v@0h zvG(2#|= G8p#-8>R>#q2GXW zcz2NGz(zSv"Cq- L `IR# P;%zvj>K`pu`N8tN@q5W=2Ezqz ^-BpE9-XGW@+o|Sq2N^L'qXp[p9GmC`+Lv c0C29eX9 '_8dP&!G{Js?. 4l Lce<p-u :Iv5YcccLr xFF[c g]GeRh l=0]"=t{*y?~#ey0- e0Vv\j0,20W'G=m#tBLpuI0 }`zcvhT+2SO G_n8=)Lzg 6F+1'{a8XmSl_%(0['u-,  N }m}|G .[ 0#g(G#:X=-,  ?,(2 9 %qC-;. %4#`:G8 K !4BBGViO  4I 4:LTB(,+N2J % 1#?;I 0!4I%9?2#C %I !  !  % !    LIST\INFOINAMTritonHat #006ISFT8Awave Studio v7.0, Copyright 1993, 2000 FMJ-Softwaresmpl<X<JFchuck-1.2.0.8.dfsg/examples/data/hihat.wav0000644000175000017500000002544410600421722016713 0ustar piempiemRIFF+WAVEfmt DXdataP*% a!y, FIk>'3>>^'pױ/\-$R9| D)`*41p , Z1L o6Q3$2GxY ϗw:S#(84w50ϫQ)Z br3F{.Pi7H!ekA!<] J RU%M H Qb#*d51ӽu'Q J`ғe]7>O(}CJev?(? >*64K3@ M;ܲK` J.ghZ] . sVl 0ߠ%(;߿G†HS r(.-s(T< ,d9!$,uޅk+'l_%Y'lܙ1+O. vwDJeއ[!a,Jß.TQ\ʉ Kq6i ! zHۈ-ٲ($ъ5\8P,W7S'G ٓ 8 .Ơ@ռ#ĉ7zS/Fu gw sY3Sv+\!Y N F-'Fc#0e]1$!-@rе?Cߘs)inG=ݰ#w !,J%rz |?=$x r!q/4! 5G;a[z<~q(3_$TCFSq%Ќ"E 8N79.Wˤ ,(  8i.3y,?B''ع :*TaE"B4x6 %pKK ZRbd*(pώ#W !'A<4O< M FH}. j4I: 5  KN] #])~$1пU=  ڈ @ 7iEk) J#Ҋ" oHgd,v :HG D J ./K "3d hmN$Y6/ Q =  >H xI3؈U-ݽ'ab N  8Bl$'!s 77kk'<Ĩ>zd%:*U@ [tvuR"zpk (+l @'3 4Z J G 1 6i=e62È'  f)T (p 0_f]I;+.%GWUDXyp v ST U/%K6m   ! *@s A@syeU .#ڇ d[ W K }( :/  ,5 g*$:Jc+XL )U  gN a>3!'OMsB  M~jkd@@e0AN wG|vrL bNUx@f.5rAW 5_ R R  #کT|K2aa kp*-, t  ' @} eA!<):f  F;9Gz:7o  ^_i 31  P @L @V [؎   M' 4 p}a+%Y.63A)u8# WH:HX]%?a"( sI! bj@{ 5$<i/9h]qF _)y !K@b +w-E o:m'N T'*9 S1[hE*h  Ct6P u/Xc[ YxG&; KDg0 ?: M) n"V% t,_M U f_ 0/zM HO\S a:vg(${dkUV@ G k{3-B  c@_ e.??DUd,fhGE** @Fe:G( ta~s  X8@N^BC& -1CF"k Xsp})O) C:]( [Q:7I%,$v L Q#uK]kzX UhHU 7 B QhceMa5^:e f`p|\ R k:@ 'C[{< y uhZ&ii^TA (H th]QE  /=Kw*SY zC> gFu*M &QLjzrYy[}EIMW S z b:dvbd*qe+!-pm G3ZXQTdYY2d!+omE FBEz+4+:%i9S+ YJ$4[.hwC,-0ozEQSJx_s?6 |.G[2e6iX+6A@|E"]Eqv+d"BV *:+%qQgRuBGNT9& u)|kCeMpM^fk@:F8 A zhjA?U:[@;rC(< qh_Ar1kfc{%1 PT~g"BW@\w}bqm(%0LUj+Lo808S:}Z;_Q2tt'M)@Gbp.nq` 4YB"DOt}3n@:M$W z3PzGYzH"zxMXa%.8dJb~(M8r h >S5M^L^gRi8pX23[4kz%kw8q27bE`^({nVAPLZzhsAlW,qH4hh eF,;}t6_z&(ES^yvXz@,\z}m A6XZ}M"Aa5(1y"Y9^m|"2e.ebJ ^//b J [4" 2.["J:ULve5L:R"\n>&/+W+tvtE:Xk"Jv.h(&nwfx><vbBgQFb8^&d B`t  JR"GtmWb"Ohm.n_\} Q(n,_kA,H/v S94;XTnknE.|d*tkQ(n5dKz(l(q@Ct[%bvn:en+h"QM}bLt ^4znY" dzZS&Vp.E4nYY(YAbHhDxknh_ LOkzhn[MX(f|3GkEL+Xt(.JYh"A:^z 4yz4am|4@z8eAd@(M4EY4(%^GtX@(J zGF\Qv @zAd(t. ^":(@"U;(va;:Fnt@g(,FOL.".4(hnd45JOKLzQ4Y4 @:X&( E@K. @"e ` >XAn+:L;\E:+Eh"vLW@%5M|^ KnXt44b.4%t@ Up,4;tzQ[@G m@bbnnmMS|ngz"[SzJdz "4EFQnhzL h^ptz.E zzJz :Q">znRQL@z@%DM4\vnFz.tb:QnF"n:E(A L"L.Y4 (@X (t4XznnFy@xdmY^WbX.W4Xb:.S.Rdn"\@4tn(.\d(@(\n t FzW4@dbW+LE t"EY@h_X \A:FzR K"QFW"(:"d:WhU@Ot )2]> 2,D2_h%Cb%Gb5Xm@ RP#etOnI;sbEM.G afal(h,EYd~bfq@HT k}: .rb#Aqnh@w ^X"{&8x"/=Mt22k7JGGx,=h=Yu( \\Od.~eIz=ki,;_ _bVq= U1If,Y@(2((A&O&"S;/s5Ay75(DyM& [7%(.V A) b5+"g7%A/==:%1"/7 ..#Mw7A=M5, )% 14& S ;./  %  +#") "    LIST\INFOINAMTritonHat #008ISFT8Awave Studio v7.0, Copyright 1993, 2000 FMJ-Softwaresmpl<X<'chuck-1.2.0.8.dfsg/examples/data/kick.wav0000644000175000017500000010733210600421722016534 0ustar piempiemRIFFҎWAVEfmt DXdata $7]u m'0;DHaVekZmPQK<1K' %{׳NѺ"(f͹L"!רq  *3;AjFHRI$HD?9]1B(J cE(*ʫlʱ ,+~0Xg| z &Z.5gjɰ5쵤˽_$ɝ ד*I 2$,d3*:q@EI}MOQ=RkQIOKxJMFu@:03*A$I L%ۄO΋^񷱵4(PNJ&ō( }^ '.5LXS]OJ:E?93]-'? C w2Oo|J``>^qӣܣU]eԫm Q$ TQ!4',1@7<&BWGLQaV6Z!]_a9cdd|dcca"`i^ Z^WT~NYMIDB@:60+% OE B j@tH =٧(ێjA7+ pמw% &b o5΂c,}[ "r#5(,k156:>@CGaLP_T8WOY)[\^^___P_^^\n[Y~W UROLI4FB>:62j.)%E!YW \$Kq׋Ҭ=xRרۤ52Y։t쇢V[ҌPOܘ`#;\˭Tڴ7êǎ˩ϙӀ_VHH`D65!  VE!$P(,/~3O7;>CFJ3O SVUZ]acqefhiijj\kkzk\kjLjihgfdNcOaa_I] [XUSCPJM$JFC@<96V2.*'$ (+ -{/d}܌ءԾ@ɏ4˴Ϯy.(>N},=aN#+TXɔƗl͝(ɯ|I6OnqiMٿ^5f u' t=:"N%d({+c.&1479m-U= D2rJ"$?')?,.9136]9<>hADFI}LORUX[^aidgMikmo&qrstuvwx6yzzL{{|$}}~o~~kc5~~~}$}| |I{zyxwwDv5u*trqqCpnmljisgvec?b[`~^\ZXuVUT)RPMK@IFDIB?Y= ;8$630E.+m)&Q$!*"U1 PmPOZ4,O߽)g׸_Ϧ/ǔ iмg|hf{hʠKŝ:⚟g2:\i*FSڍ؍1l7X̐HʑIݒx\SۚͣE&̭+e e.ES9Լ֭ڴ܇~o|pfW=GH(S= edN "${&](B*W,M.H0g2I4 68:<2?rACFlHJMNQ5S!UVX*Z[]~^_`bccdVeffUggjhiiijj4kkk+lAlXllllllllllkkk(kjjj|i#ihhzgf[feepdc cFba`_M_n^]\[ZYXWgV\USTSQPOANMKkJIG/FD[CAq@>P=;[:8/753x20G/-+W*(*'%#M" *GI  }CO6P(s-5w޸ f +]Ҍ3NaǞ:Zڶ+ޱVǮ<<بtm6𠛟TșmgffezW?ߋ+4z`󆆆m=g_zل H{X%_~?勬Bѐ—̘י]CΤ JaHx\˷Aº7,T¤ų5ɬXiћ3c ڹ>ކP2Lm ]mS= U ?w)i\5 7"#$9&p'()[+,-/Y012N4t568U9:;M=>?jAB>DE(GH?JKXMO~PQiST=^<;98=754Y320F/-,^+)(*'%j$"!\ .lMZ{ 7 LN{JU%w`aH.jXE'׿֑|mL73˦ʖ|T5¢h@*ܹҸзȶǵ˴Գ 1Uw$Qͪ Dק nɥsΣ(XŠ@?ÞEϝqk#ߛ[䚸gI$ ݙ7Xޚ=t7xVZzL|SȢ>'"0Qܧ_t NPW o2zGշc?#ݿļŶƵǶȹɷʸ˺̿,A\jwهڤ %Kx+?Qf{'Mp5Rn  & 8 GPYcn~ueW G!7"&#$$%&'()*+m,S-;.$/001234\5:67789:;l/?"@A BBCDEFGHIJKLMNOPQRSTyU]V4WXXY6ZZx[\\]]]i^^0___P```Raaa3bsbbb c3cQcmccccccccdddddddd ddcccccgc9c cbbwbAbbaaBa``_``_k__^c^^]F]\~\\[=[Z\ZYvYYXXW WV&VU(UT'TS&SRRQ QPOgONFNM MLK`KJ.JIHQHG G`FEDODCB)BlA@?&?[>=<;#;L:o987655,4A3Y2p10/.-,+* *)+(9'E&U%a$o#|"! %.9D O T _ e lty|0E]t6Tr9\{ݚܺ=]֠ 2V}УEp˙>gƐŹ /\ھ1aJx۵E~9{ï Y[]ѨHçBĦKեaR򢔢8⡋8蠛Lu0힮m4ŝ].ۜw\A.#3KfɜI}Y؞b<ܠ.ء/AdȤ1pߦO5%"4G֮eI岂d _r)⺚Zܽi1c6ųƈa9ˠxO%вюjF$ֶגmDܡwJ_.`)Om0BLQK Bz6s3x9 H  ` '}D g1Wx@ V !P" ##~$5%%&M''(V))*M++,5--t.//E00p122(33D44[55g66s77t88u99m::a;;S<<>==&>>?z??]@@@AA#BBCvCCZDDAEE(FFGGGtHH_IISJJ@KK0LL MMNNNoOOYPP?QQRRRaSS3TTTcUU!V}VV3WWW0XXXY`YYY2ZpZZZ![U[[[[\8\\\\\\\\]])]9]D]M]S]S]U]R]N]D]<]0]]]\\\\\m\L\#\[[[s[?[ [ZZ\ZZYYQYYXrXXW|W%WVuVVUVUTT%TSTSRyR RQ#QP2PO=ON?NM=ML0LK"KJ JyIHYHG2GFFkED6DCB^BAAu@?/?>=7=<;<;:91987%7s655[432@210 0i/.-B-,++b*)(6(~'& &N%$#"#h"! <  U&mCb7^<  h  O 7#ve _XZ^ hu*B^}>f.[)`2pGgC޲"ݐrS9٭ ؕ|iR>Ӷ+ңё ЁsbTD˽7ʯ)ɤȔ LJzncWLE¿B>==CǺKйW޸h|%Gشo6βk H갌5ݯ2ޮ@󭧭_ҬOثd.˪pE ةgQ=,+=OgةCmĪ&ZʫBìKݭ*xǮkįuѰ2W$j״G2#7¼Lܽn&U$`ğBƋ0Ȁ+*̆4ΓBШZw,ՙQx/ڡ[݋Ex4e!VFw2aIs*Nq'BW mw'++{% r  a  G*f>s <i&Ji)>N [!!c""i##j$$g%%c&&Z''N((<)))**+++f,,I--&../l//C001}11J223y33=445`556z666777E888P999Q:::N;;;E<<<7==='>t>>?[???<@@@AgAAACBBBCdCCC}>>=/=AB D B @ <::89>CMX g|8Tt=i4l@^<wbN@ݺ5ܲ-۬)ڧ)٪,خ3׹>Ocyӓ"ҵEiϒ+[͎+f̤Gʋ0{"uw%Ƅ3řKŶj$ÓM ƒ>z:FͿ[ 龰xAٽq> ۼzKûk@Ǻ{U0ɹiM/Ÿm[I6' ߷طηɷǷ··Ƿɷзط/>Scy׸-OmӹElºFwջ:nۼJ4p,l4yI h²H×/~kż_ƱYǯ\ȳ^ɷiu,̆=͜Vδs1ГQѴx;Ӡf0Ք^+ב]+ٓd5۟ sHݲކb9\:fD' `D*qYF1 viXK?4)ysnkfba^ZXR P L H D >8.&  {k_P=*tW=" r N!!+""#n##C$$%%%N&&'''I(( )o))2***O++ ,h,,-x--*...1///2000+1}112n22 3Z333=4445e5558666 7L7778U8889S999 :L::::8;q;;;;>l>>>?7?e????$@P@@@@A(ARA{AAAAB4BYBxBBBBBC)CDC[CtCCCCCCCCCDDD!D#D&D(D*D(D&D!DDD DDCCCCCCCyC`CEC,CCBBBBkBFBBAAAtAGAA@@{@I@@??f?,?>>q>0>==d==<,+^+*{* *)%)(=('U'&j&%%%$$#+#"9"!I! U alt{ "&*.46:@DL L R V ] a ioy}#1AOap#=Wr<]=g(X$[.k L0wd [SRX dt'=^߀8ީ_ݏH܂A>ڃE ْWتq8ד\&ּֈW#սՊZ+ԝnCӻӑe9һґiBѣ{V1 ЙvS. ϟ~Y5Ϊ·cBͶ͖sR. ̦̅c>˻˚zX6ʸʗzZ>ɨɏsY=% ȬȗȂmZH3$ǻǰǪǥǛǗǒǏǍNjǍNjǏǒǗǛǡǪǯǻ +?Ri}ȕȫ6Ttɖɹ#Hoʗʿ?j˘#V̺̆S͉Ϳ.gΠPϋDЂAуKҎ]ӣ2x V՞7փl׻[حP٢JڞH۞NܥWݲ dy4Pq2Y!PR"^1pI"hE!qO0cD' }`A& |bC& {^A"sQ0[ 5  ~ U , j=xFxA l1Nn&8CKIA3 m P *!t!!"H"""#X###$^$$$%W%%% &G&~&&&*'c''' (D(x((()P))))'*Z****(+]++++#,R,,,, -:-i----.@.j.... /7/X/////040T0w00000151R1p1111112.2I2`2x22222233*3@3T3h3z333333334"454D4U4g4z44444444455 5*5;5G5R5^5j5v5~5555555555555555555555555555555555w5j5[5M5>5155 5444444u4]4B4+4 43333~3\3<332222i2B22111x1N1#1000m0@00//}/K//..~.J..--l-5-,,,N,,++^++**d*"*))`) )((V((''D''&r&,&%%U% %$w$-$##N##"i""!!4! I [ kt!{'-/+|&tmb UC1w`G/ n  P / n H !\4n B{MS%\,b2h"fJ5}h\QIFEMVe|+ߒI޳k!ݑL{:۳r2ڲv8ٽلHؠh/ב],֚k<մՌ_6 ԽԘrM(Ӟ}]>ҩҎuZA(Ѵўцr^K7%нЯРБЂveXL@3'ϷϰϦϝϓϋσypiaYRKC>70*&   %+4>DOZcpzωϕϤϰϿ)=Qe{ГЧо %>\yѕѴ2SuҖҺ*OwӞCnԚ N{լ ;m֟8pפG~ش$_٘Gڅ9w۵3qܳ1rݵ:}GߊY)pHiE(p Z@)|eYJ@73-,*,-287, p_L2`>b6|KVZX J3 n !N!!!!%"Y"""""#S####$A$o$$$$%K%w%%%%&>&g&&&&&'C'f''''' ('(E(b(((((( )%)@)W)o))))))) **0*B*W*g*x********** ++ +.+6+B+J+T+]+g+l+w+~++++++++++++++++++++++++++++++++++++++++++++++++++++t+l+^+R+E+8+'+++*******p*\*D*.**)))))u)W)9))((((x(U(1( ('''y'P'(''&&&X&,&%%%w%I%%$$$[$($###_#,#"""W"#"!!~!G!! f 0 H ]"p4}BM RX[]_[XVPIBz8o- e ! Y  J   : o - `O ?p-^K~7i$S>l(Y?m&T 8cIr+T:aDo(T }7cL|6e PCx5m/i)k+q3}AVs:a+ߏ[)ޕf7ݪ|O%ܤzS)۲ۍhE!ڸږvV6ٽ١قhM4طء،tbM9%װנד׆xk_VI?7,"  '.5AIQ\bnvׄ׌טץװ׽ (;JYjy،؜د!9Kauٍ٤ټ3Ngڀڝڸ *FeۄۡۿBd܅ܧ6Y~ݣy&bQC}6s+k'f#b!_^Z[[X[YZ[X[Y[[\[^Z\]\_ `#a&d" a # _ ]  Z  S MB8v*fX E2lT7rQ/e<qCyDu ;j*Y<i<f 2 X  !4!Y!{!!!!" "?"_"~"""""#+#F#_#z###### $ $7$L$a$v$$$$$$$$ %%+%<%K%Z%i%w%%%%%%%%%%%% &&&'&/&9&@&J&S&Y&c&h&q&x&~&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&t&g&Y&L&>&/& &&&%%%%%%w%d%M%5%%%$$$$~$a$C$#$$####`#?##""""c":""!!!n!E!! g < OU"R}Im2Og0F Xk/{>L\ j.w:HXj/ { ?  T  e * x ?  W  k5Mi/Mj1Lk4Sr9Xs<Wt:Yq9Rk4Nf-Id+G b)Hj/RwC k5a+X$W$[)b3pC[,wMqIxN(e@iF&aC#߲ߖy^E,޵ޜއs_I5#ݺݫݛ݋~rcVL>2' ܻܸܴܱܮܬܪܧܩܧܥܥܥܥܥܧܩܩܬܮܱܸܻܳܶ "*1;BLV`jr݈݀ݔݜݫݹ&5FUfwއޚެ%9Ne~ߔ߭*F_z +Kg ,Or+Pu>h?m"N >o7i8m CxX9pVC~0k ^R G@~:x6v2p.l,j(f$bZU K?}4o&cQ@z)dJ2kN/hG}# Y 0 i > s  E y  I { J{Ds 8j*\Et,Y 8d9e 4\"Lo-Ru)Lq;[|9Ww %@[y2Ke| 6K`v';J\m|  ! . : H R _ k u !!!!!!"!%!)!,!.!4!4!8!9!=!>!B!B!D!E!G!G!G!G!G!E!G!E!B!B!@!@!=!9!6!4!1!,!)!"!!!!! !! s i Z M < -   ~hT>'eK.aC#Y8Z2 lBqFh<V%d5q@ uB r> l6c-SzB h/ Q  t <  [ " | C e * Lo4Vw<\'Ff1Qs<`)Lr;b,T{Gs= j7e1d2e4n> wH[+rCd6 ]5 e=uL)mH#sO.iK+ vY;z_D+|eM6 q_G5"~m_O>/}ocYOC8/% }zzuursnpnnnnlppnrrsuwwzz ",4>ENX`jr~#2>M\kz 3EXj(@[p"=Zs#>b!Ch;`Fm7b8eCr*XFy 8k1c-_.]+_,`/c5f8l >sEzKS%[/c5j<pDuH|NS T"U T  N   E t  5 d & S ;fGu"Lx!Hr;` Fk!Dg6Vv2Pp:Tq %<To 3G]n,=JYgt #).07:>DFIMNNRSSUUSURRPNMIHFA>:72-)# yog\RH>8-'}sg]QG:0$ yk[J<- o]I5"waI5mV; }aB$pR4tS1d?gC_8tL# V +  Y +  ~ S $ s H  h 7 V)rE^/xKc8 Q"j< T'n>V'k= Q#d6yH],k: |J_0rCX*sD`4S)~P&}T*_7rO'lI$tP/ jL, uY<|cH1qZD0{jVF4#zn`UG;0$wrkhd^ZWRPMHFDAA>><<<<<:<<>c&Ls7a)RzEn>f6b 4` 5b=gCr"P{1\An#Q 5dJv1\Fq(V :iL{+Y 6d B j  F n  D n  ? h 6 ] 'Lr3Z}9[4Uw@[7Yu $?\v,E^v-AUk}):J]j{ %1<HR^jt~       wkcUJ@2& }l]N;*wdR?+wcO='iS=(u^H1qZD)~cI0x]B% iN3oR7 n P 1   _ C %  j N . m N - f E # uQ. Z4{X1 sM$b9pGzP&~T*Y+X*U(yO%xN"uKvLxM$~V-b8tK%e>a>gB vU1oK/ sV8iK.lT8gN5w`H2v_N:%uhUH7* yog]TJ@91*" ).8>EOYblr|#2?N\kx':J[j} 2EYj~.BVl'=Rh|.C\p,DYt!Yq5Md|3I]s*>Teu&5FWfs #.;CO[emw   {qg]QG;/" ufSD3!zhVA,s[G1~hP9# gO6 uZD+{aG/ z _ D +  o T 9   { b E )  g K 0  h H ,  }]?!kM+ qO1mI+b@qP, |[7`=fChGkG"mH'oL'uP/}X4a=oM*];pP0 nL,pR2|^B#x[?&hM4iQ:" nWA-{hTC3 qbSI8,uof\RKE;4+%  %*29>HPY^hpz+7BP\iu-=L[l{!2DWfz "4EYn&Up/Jj2Om!?]{7Ww8Zz@b*Kk3Ux Aa .Ln8Xy?a'Gg /Mo2Su9Ww<\}?^ A_?]} ; [ y  0 N n  @ ] y  % C _ |  ! ; V q (@Yp2I_w%;Qex#5FYhz$1@NZgt!(2;CJRY^fmru~|urke`YTJA92(!vj]PD5&wfYF7&{jYE4 |gSA-~jV@- u _ L 5 ! u _ J 7 n V B *  n W < & w ^ C ,  sZA$ fK/gL/cC&tR8_?!fF&jJ, kI- lM, lL.mO/qP1uT5yY;bD$kQ1z]=!mR4lN1sX>#oV=" {bK5mWC/{gV@1sdUF5&vh]QG;-#{slga\UNLFD=750+'&&"!$)).35Yr'AZu % 9 T l  ) ? W n 6 L b v   / C W h |  $ 5 D X g x '7CTco|(2<FP]dnw    xpiaXPG=7-$yk\MA2% } g Z G 8 $   p ^ J 5 #  o ] G 3  s _ H 3   m V @ *  x`K5 oWA+iS?'iR?)mWE/s_I5t\F2iT:$ mS>& hM8 v_G0mW>'jU='s\F/mYG.xdN:&ycQ<({gSB,~kWC0q^L8'raM>- yj[L=/sfZPD:.$ |uoja\WPKHC>952-+&&!  #&(+/49<@FKPU\afot|)3AKXdq{ />M^m~#3CUgx /BTh}+?Rfy 5G]q1G[t 7Mbx)>Vj2H^s ":Nbz%Sk  :Qg~  7Of~ 8Pf}  9Oh~ !7Pd1E^t#;Oez $6K`v  ( > O c w  2 F W g z   ' 8 I X h y   ! 0 > M Z i u   ) 3 = G Q Z e n v  "#%(,,-/-1/11/11/-,*('##   v l e ] V L D ; 3 '     u h _ T H < 2 %    { n ` S G 9 .   u g X I : -   r c V E 2 %   q`P=. tcRA/ ~n]I6%nZH5#vcQ;,vbN:&~jU@*{gQ:$pYA+mYB,pW?)jR9! gP8 ~dO7! mV>*u]H3oYA-lVB.zdR<+q^L;,wdUH8) wm^RG>1#zqkb]UNIA<50)&!  !"'+016:?DKLSV[`gnpv{ '-7@JR\eoy&3>KZdr %6DQbq!2EPdu$6IZj(;Qav&:Nau,@Th} #9Kau 3I`t 6Mcy)=Sk 1H^r#<Pf|,BXl1E\p0F\q/CYo+AUk'=Sg~#7Mau0AVk}  - @ T f y   ) = M ] n  ) 6 D O ^ l y    ( 2 < F O Y a k u z        " $ + , 0 1 6 : = = @ D F G G K L L N P P S Q S Q U U S S U Q Q Q P N L L I G G F D ? = ; : 6 0 . + ' "       w o h ^ T K E : 2 *    ~ s h ^ S J = 4 )   x k _ U H < 2 $  w m ^ R E 9 ,    pbUI:,|k^MA0~n[L;* }mZI7$m\H6"zfS?, o[H6#s_L8 pZH2 yeL;%{iR<&{eO;#v`L6 r_I7 yeO;'wdR?-{kWJ9(pbSF6+ti^TH>4*  yqj`[SLE>61*$   '/4;EJT[cjt{(0:FPZdpz ".:GS_iu *9CQ^jv-:HWaq}"/>LYhx(4CTcr&6DUdt 2@Qap$5DWgz)9L]o&9M_r 3EZn~ 1CUj~.AUi{*=Obt-?Rds"4ETgv(5FTet"0?KZfs  " , 9 B M Y c o {    # - 3 < C I R W _ g m s z } z s p g d \ U P K F = 7 0 + #     | v l e \ R H @ 9 / %   si]SG<1$yk^PC5( }j^N?. udUD3$l\L;* p_N=+ ~m^J9*{j[J6%xhWF4$vcT@1 lXF5"~kYH4#j[G8"rcRA/ rbSC1 q_RA2wjYJ;,pdUG;.!zocWKA5(vl`VOG=3*  zunid_\URMHC?<852-)&$#!#$(+.28Oct)<N_s':J^n 0ATfu ):KZix  , 7 H V c o ~  $ . < H S \ g s }     % , 3 9 @ G N S Y ] b g n o x { ~ } { v s o j e b ^ X T O L E B ; 6 3 * ' "     z s m d ] W M F = 8 - (    { q h ^ V J > 4 *  {nbXL?5)uh\PE9+ vi[OD8)|ndUI:.! wl\Q@4# {l]PA2"ujWH9*t`O@0 mZI7$m`L9'q]L<(tfRA1 s`P?0 pcRC5( yobVJ>4) zunf_ZRNFA:50+&  $()038<=DINSWZ_dlnux}  '.4>CLOX^glt}&-4>HOU^hpy")18@JSZblt{ #-4>EMV^fow "+3:BKU\bisz ").4=CJRY`gov| #-07<AHNSW^dhmsx}"%,038:?BGJNQV[]bdinqqty}}~}{xxtsqlljgdbb][XTTONLJIEB??:8631.,)'%$ }|zxsspnkifdca^\ZYUSSPNKIIDCA??>:97550//+()&#!! |~||{{wywwvvvrrrrrqoqollllhhhjggggecbebbb``^``^]][][YY[YYXYYYXVVTXTVVTRVRTTTVTRTRRQTRQQQRQRRRRQRRRRRTRRTTTRVTTVTVVVXXXYYYY[YY[[[[]]^^``````bccceceggeehgghjljljmmlmoooorrrtrvtvwvwyyw{{|||||~smpl<X<FLISTbINFOINAM INDST_KICK_3ISFT@Awave 4.41, Copyright 1993, 1998 FMJ-Software;Sound Forge 4.0chuck-1.2.0.8.dfsg/examples/data/snare-chili.wav0000644000175000017500000010560610600421722020013 0ustar piempiemRIFF~WAVEfmt DXdata; Ύѽqנvր7̯֒Nв@ Jyu~^KF r(v-{,'A! $'(%`&[' _,*700%&(!] !.o:wD C;V.!,6) WE0jr+1®;IZ0 qaώ [rH izL +ܲ۵",N~Q}Y/Ezh.sz2%+: >$ #  .nҹr/2($26m/%['}7EPR]Bl|}jrK5$ IicA zQ, X"6B;?.SaJe%.4/$!T /{՜$ۍwJЬʹԔ+’y]ݪU&mfG >sWϝ/ 2lFBNu}@S d Q _YfN$-!3Y3Q/,+H+ 2S:;p4 ,+>3:b=?CHHPLOGTEZ_`_8W;E.lV  /4L+l n2!U7$ :s m_f5) TyUӽGJ\"~K7aBʹݵ5E9cj20*ms $r(#pJ7MK]>45BWa`itwvgpD`ZPG?C2# - 0 r(e%$!Nz# 9xjfUf߱ ,%9FDoQ rmMT\%{lź=]Ĩ&&ɯ=XK'12.)(.30+-M*quQ D ~F:xcU|I>"y")>3?KOWE3C,0//6Y3'9%I| h'/|& zG~P-;}aِc*=ݳV<)m}";n v%%r>N%ǻŒ} \!7#$BO, ;, R25 ) w'.?O*Z\WLDAFMK#D;5>-!Q)Y32-/>3V( ST2ؼ3Ciӿo9V eC-;cR0 $~5҆̓\7{`:#G3 m(u,NYpS6)@ s #(4 .0.0-(-44*F &)_,37.#$)! Dz  BE 7#2$ ;Lٳ_Vݣ,F*9ua}`WdWaj&@u$%?ׅӁкxڣNoa#4T : ݘ*/Dw1'F, i d Q 4m)p44}4hV^ۓр"ܺX%޺#!kX"% B ^l#ЋV݀D(!}!? "&#Q)M*a?''*5 o_GsYl QuGc>7 ,J L WP Sf |v]5 L ~L n#$X"(v-)(>-M*S D ZFf ) &W nlmYN̓.TXQ# (  s"[-G1H+$?'`&4G -q fs1 p2r4;G l!<Gf+(&uIvu? &Tju2l+ a7 Q P 2U^@aL$a 5 %?7Yxc  Y܀xDcCvM IL  ) ;09 2 Q~*A!''$!BiFArvZhWܨݤޭhV - avZW;AB #a  ^%crixAO I7̧h %vs>F,o ^/o &$%-] P ,LH Zf a "&"*[-v-09\m^G Fho-i ~{z -D :i.er~,i[ D`Wh,P;L w = I^ ^@;6[ZfTzڟxjhPnL  aJ7i ?''""F'',&#|&$Nj$N$Fd5 TG=UrKv,k߲h߷ڕY^zU : S: T Uw
@^4i s c2w %&oaxSI)11H^O 5) O D iL ^T,@ uLz/fI _5 -@z$:m'w 6Y -chzQ ZM V,i {"_B,J|\ QID^Bߕ)$\-;?  GA0  h5 ^,mzhCPcRT 'L .Avd_   # 0Z W79^"#@F%& :   : _ 1Nrrc&zjz L 4 s# | d  i  Oe+?}'eUm 2 |  |  auUKTid# [ n V Q B D : xx 2/9#/uE2 s %;  | iV  0 2fYuxdz+EKIaz !H;z uw V s 5  B : Q w  RO 7zXmQL"s > - sAP1ZC"/E2 _Z{ _s  v --h\#`9*a/  G>? 7 n WV G IV=>F2AMs d [c/9rs GldW - On : # h[N$NQchYfZ4UUF2j;j=2a  Q  z"E R ?mr}jXK]6ER[ , [ ( ( D J-fa7 a) oxD   2RhPU@fx,V1';T "cMYcmQAew-@zhm^^o'c=2z7|-\i71C 6, DN[O(  _ V5Z  =@+  =mA-@n 4Z2a-WjJvNn,h V ? 5BdT"Z+rh2 r!xaKxmhzc hYs |  7=cvP+WMzvcC^^H=RnaWRinMir&7z=D : J@@J 2&uf,zQV{C+Fz@IIi vQ  =!/>9^A\ i 0 D 7o!YT& VHP9KPAun( 0 _>q:d,( \Fv J UPP>^;n "P%7;  2af&&hs  w ^z>F111cUzeezPzTM W_  w | w i  ?  a!j 7 ? sOK"/cA/K^UF>1HJW-zu&7f# ,G_ I , - #  ZUHzmLvPh+|xE2-@fMxd| ;-zoujjc1m zccKm^-!)2%xE|@M &=jh+77Wr,r4LPO^!2---)D WYcc9m'{h> niEO-  RxAF4 VDIni Rs G 0 |T!cFmULz44+&u n 7uYP'+K =\  s # o7TYP1SIIwCUFo v 2nn%^LU/9a;7ucKh=Tz L' UoAo@nd >q M u7;u4K6w,6ew^mmzE7uz+% ua| 5  _ | %rL^,1V KT%%; sR- Jj7zFArPYoY&YJ o\+K:7J2Oa  7@Y2h#/Z'U\F=%d _ d ' aouOJ|s) V 0 D ->'>:#m4h7j@faiIMdD i||EO &7&o7F!!ni2 @E\W\\@M A4rUK+huYOuT2"&))J;  --a;RT+ZzPJaW;|aj-JOT2Jhm^)z2d!/K/KCCORR| n# s  Y1mU-Ouuu^h^ a^2|snn;I-dD %1QVw4+c&TjJ |=Az!z|nW%2rrh6QHc&&7 D n( 2TYumhFU'=zuTcOzuz2\%nO||f; Fh,1cm6+c%Wn # |f fO-fJ@s-7FrmzCYA);;I[ Id s V _  AAc+'ZAz&T2TYOOmc=zF=!j^YOT77\)  2YAPhhmrPc!7& YYEj|; uF!&&7x|%%%|z^=^4V1Z9rEj7AFzoE  d7RsE2zuAKFYz -JoY=YA>9Ur&FY%-7   \ ;i;)oK>rZZFjjoT-OJ|@-J|x-2x\W YO49mm1A oJ%%@MIdnsE;-o^=Y-%Jo7f2YYu7!m9zzO|is # %|O!!u&Q^cKF=uzY4r/=Y7^!-J-- TYYTOz7j7F/v>C/+FF+UZvc AY|W7aTj ^!uoY=zFPm!AAOTa%RsJOhPZ"72J-o77!c) nfOoooTzPmh> Prmh 2& |ajYa=YTOTz uj27! [r1h>uu%@W\aWa+m4+\;@!^z=m+u2f|@|O!zz>"C^vc!oo7uuO|E|;\-J|O-7O2jhPmmmvr uoTWs\ RRRI2M7 )fJOr+uAK4Pu! A=oOY7- xaE\WWs @|fO^PUUKFKcOJT7uu7-a) );W)\\|fY//P'^9+A=2Jfj- Ef2jT=uo2 FFc+Y a T+c+c^&^YTjO2xRn7xx2u^&+'H,r/h++&J)aTf&+&jOE joj)%fO|a!h9PvrmhA |)j |@E)|;O77^ &^A&z4c!T2j WJF&4"ZU 1 /FAz=TTTuTWi-EE-oYz+mrrPUU"r994Y7o-||jJ-j=Y=^c7ouOT7o=z 'K7fass W@x cKv4Aoj-a| o2O=u|a\W@xsRx%af2=9r4'c>'zmPKz-|W--JOaOjOf-jOO7TT^c/Ur=o7T%@\\a J7oO-JjTu&P4PU44/K^!&Fhhz!&AExx  @\WfTu!u+KhF+K zAuTO) -Y!2YuYj-2f  O=&T27uhv"4j-)7Rs|f2TuYTT7Tj2OOO2Y &AY^Fc!AzOj-W7MM7x@%|)AhPU9UUPKuT77!T7j-2T2J)aooToTT7z& rmz=7o E%WRR;EJfOuou!777om4P4Pmh u7o7|@%E| fOOuAc4KKPP&c^uY!oojff) ; ajfuzP4mPr9m ATJJ-a\@@;\)OOJJ zAA=u!Y77zA& hmK=TjE) | W77 \a-TYuzAz&hm/+F7ouoO2=7ou^AAjJ))7TFcFPh+++&-277-ffo!Y7o=A^zzA&AF+h+u2-)\%@\\%)f-oz+Az=T2OTzAzz&&^zz!ouY! z!7E@;;@xs \\%|OTccKAzY=u!!OfJ-j) JjoOj72o!Fmr>>44h+&)\%\|Ef7=zF+cAAz=Y=u77zA &TO-)@@%%%%aaa)-! &Tjj2j7T2OJEj2T7zYuYKKhFc)))a ff-T==jY^^^& ^ c+FcKF^zT7o2-   |\ |O hhK/hz!uA2T2o772&=OaW;%|Ou=z F+FFc+AzYo2O2OJ=z^zzzz&&u7T7ooTu!!^/FFKh++/KFFc ooTJJ a%E-o=^zAc ^Ac++^!OOOj!==72E| fj-TT!&cF+cccYYO7oo2jjjj--j2TYzz ^!TTuAFF A^!o2J |a2j7Yu!!Yu!zA ^!!=o7u!uuu&Azu7E\\ f-2T^^/P4mYTj-a| ff-27!!!uTOj2ToYYu& AY=zAzA cc ojE||EE|\af22o!z&+F&zuuu7ToT7u!77!!uo2f%  )oYz^&&zzY2j2777ToTTjjOj-j2jzAA& &zA+ z!!oToooouYu=!!!Yu!u^ &&cK+ AATTojfjjOoY!!uu=FAzA&zzz!Y=TooTTY!z& ^zYjEEJJ) -OzA+c TTTJ)E) ) fJOTYYTT7Tuuu!= =!=z^^zzYYOjJfJf-jO!Y=!^ A AzA&!jjj2oY^&T2OOO=YY=^ Az^^^YTjjjOoY!uY=TY!YY!+cKA^=YO-J Jjo=zz=uOO2TT7o77o77o77O-fJ-Jfj2OFc+AA&^z2jJ E-jo7TouY!===772jo2J7u!AcF&uuTffJf-Oou=YuuYz!^z!=!YuuYY7ooTo2jOO7TOO2j2Yz c &^^^u7jj2oYuoTuY!A+^z ^zz^ &z!u-OuYAz!!=TTTT7T7u=Y=^ &A=Tj-J-JJ2^^ ++FAzA&&!7Oj2OfJj-fo7!=727uuu=A++A &^z!Y7TT7oOJJffJJj2Tu^&&&ccA^uoO27Tu& ^=Y!TojjOOT7oT7u=!!!uY=u=Y77joOj22oT7oo7YzA^^& !Y7jjOoTT7Y!=u=Y=!zAAAA& &^A&cF&!Y2aEE||EJjoY^=!u7ToOOj2Tu=u7oo2To2fJ2OOTuY!!^ +++ Yuu7T-f-JJj27Y=YY!==!YuuuuY=YuYYu==72-Jjjj2Y!A^A&c+cz==!Y77=!!=u7oo2OjjjOooTY=uY=!uu=Y7o2jO2OOOjj-fo777Y&c &^===YJJ22jO7=z^&ccc zzzYTTu!!=TOj22fJj7=A^&cc+c^!uTo22jOOooo7uY7TT77uuuYY=zz^zzzAz!=uT2J) J2Tu!!=!^&& z===Y!Y7oT2OOO2TToT!z&&^z^A ^^!uYYu7777ToT7222OJ-Ou!z^&Au72jjO22777YYuu^& AA cc&z=YO22O-ffJj7=AFFc A^AAz===uToT7ooT7T7ToooooTOO7u^A cFF+c&z!oOjOOO2jO22O2ou===uY!=uoo7jj22O22j2u^z^&&AzzA^z^z!!Y777o2jjTTu==YY=^&z!==Yo2-JJ2o7TjY^&&& &A z!!=2Oj222T===!z^z!=uu=!!zYTjuu=^^& cF A=uToOjOO22O2T7TTuuTu=zA^ Azzz=YTOjjj2oT777T=zA&&^!uu!!==YT222j2TTuYzzA^^zYYYY==7777TTTojjjj2o7uuuY!AA & A!=u7jfJJJouYYuTT77YuuuuYYYYuu7jjoY=YY=Y=!YY77TT7TToooTo7T2OTTY^&^^ A^^& Azzuo2jjO2277T7u==!=!!!uu=u7T77ooTToT7uYY!!z &z!!===!=TT7=^&AYuuu7o22OT7TooT77o22TY!^A &&A^^=TTj-JJ-OjTuYu=z^z=uY7TToooo7T7T2j2jjj22jOoTTTT7Y!Y=!=u7OO22jjOO2oooTo777TT==Y=Yu=YuoTOO7To7TTTT77o7YYY!!!Y7To222jO27u!AAA A^zuuuToT7oo7o22ooou=^ A!!!uToo222oToTuYYY=Y7YYYuYzz=Y772jj22Tuu^AAA&AAA&^zz^=To7ooooT7TTuYuuu==Y=z!uY=u7TooooTT7Tooo7oT7oTY!=uY!==Yuu77To2OjOo7To=!YYY!!=YY=!=7Y=!!!==u7Tjjjj222o7Y=Az!=u7o22jOOj2oTTooT777TooT7TTT7uYY=!=YuYYuuo22O2oT==YY=YY=!!YY!!!!Y7ooo7uYYY=YYY!YY=!YuYYYuYYYuuToO2oT7777YYuu=!=Y!=!===Yu7TT777ooo22O2oooToooT77TT77777uYYYuYuuuuuu7TTTo7Y==zzz^^zY7uuuooTooT77u=!!!!!=7oOjjjjjj2ooo7==uuYY==uY====uuYYY!!=!!!=u7oooo77TTT7u=YuuYuuY==Y=!uYu7oo77T7ToToo777TTT77TT7TT7TTuuuuuYY7TToo7oo222ooo7Yuu7o2jj2OOT7uuYYYY==u7TTTTToT77uuuuuuuu7777T777T=YuY=u7TooooTu=uoToooTuuY==YuYY!!=Yuu77777777u==!!!=YYuTTT7TT777T777YuYYuYYuuYuuuYYuYYuuY==uuu7ooToT7T7Y=Y=!!YuY!!!Y7TT77ooTTT77oTT77777ToTo77TTTooooooo2o7uYuu=^Az!=Y7To2oT7u=!!=!Y7ooTT77ToT7uuuToOjO2ooTuuuYuToooTT7TooT77777777TTTTToToT7Too7u!!=u7T77T77ToT77oT77T77uuYYYY===!YYu777TTTTTY=!YY=!Yuuuuu==7oo7=Yu=!=u7TT7TooTTuuY7oT777uuuuYuuYY!!!!!!Yuuuo2oTu==!YYuuYuYY7TooT77oooTT7ooooT7o777TToooT7777=!YuuY==!=u777T77ooo7TT77T7uY=Y777Too77oTTooTT77uuYuuY====YYY==!=YYYuu7oTTTToo7uY!!!!=u7ooT7oO2T7ToO2T7u=!!!!!!=oooTT77777777To7uYu7Too77Y=YYuuuuu7TTT7ToT777777uYY!!=!!!!Y=uYuuuuuuuuuuuuuuuY=YuuYYYY7TToT7uuuu==!!!!!!=Y=uu77TooooTT77ooo7uY!=!=YYuuu==!!Y=YYuY!!=!!!!u7TTo2oooY=!==!=YY!=Yuuu7777ToTTo7uuuu7uYY7To22oTTTT777TToTTTT77ooTTTToT77ooTTToooooToT7uY=u===uYY==uuuYYYY==!===!Yu7TTToooTTTTT777T7uYYY===!=!!!=u7To2oT777uY=uYYYYu7TToT7777TooTooou==^z^AA^z""???\6Q6666QQ5Q`DFFFF+,GGbbHHHHH/Id~dKK2100bbbbbzzyyya`///...EEttttqqqqZD,,,,=R==QzfeQeyxPO;;O;&%%%9L_^^^K^n\J7$7$###""!DD!! 1AQQsq`ppoNvgHIIhYYx,JXIIWI+~~ssfttgu$$$0$/$/ (44222((1;EEE:0&&&&..&-5<<<;,%      !  LISTVINFOINAM SD-ChiliaISFT8Awave Studio v7.0, Copyright 1993, 2000 FMJ-Softwaresmpl<X<[Echuck-1.2.0.8.dfsg/examples/data/snare-hop.wav0000644000175000017500000010415610600421722017510 0ustar piempiemRIFFfWAVEfmt DXdata.G,"Svt0qMsKq>rpKqpppNSBJ&<  Q5j.è,/j犻vV'YG8Sn*SGΌ:Uݍe."LY[:'xaJ %g^+gt&tssMsrr>rr2soO% Eie"쎎VV$i['[X׳>l'lԐ+Qt{*miI\qp#rtttt&tshsssshs2srr>rrqqeqpom khYghhl9nTnTnnmmm|mEmmllQllkk(k(kOjihdXE"J&@"QOa8 v ]ãyꗢQ؉zSnnnnYkr#Uݍ=LЎ(Vt$2IDW_Y@H<=3IY `)W<!OH_jGopGoononoZDp9-/,'C үү-иVo왻'h=="s(' 0 vۖ9ROޮH'㧪[FbcPn7&)EeguSqOEbpEmiAi4jlWpWpe[TJPxJ ZnpppmglnTnnmpnl9nmqC O$m+%'ӹۖ٪ݍqe:BY&Ȥ[3dsj==%e !6/t 'vo:Dfp~ophB %t]W0uG 0?@5*x DսrkɌ9 (vo٪ƻgۻx>^ SG/R㧌֒">B 77c v(vuutucQ7e>ϴBJuuؾVg2";IdAtssrhs2sh[BUF*-$# ^+$2*{"-$%V%>a8 OخӁm&0ŁиQ!ỵXکBȽ&* =0uSVZSB (qIkԴ".:hsqc]YgKqeqrWprocCWlpn^uH57,*(y+7! 8(Ix2] %:?=CMiToX[L]PV?"3jIcã~͠4ЎAǑ._4Ў//ʩ/33&M(,Ce#rsYrr^0 S777$gE(7!g ?[jog$HR! wQ]ȴfdΝx8˹Ԫ9[!Kł( UEI9C4 ȌU3қYe>!9IMSO_dYF?= =9r0c$o icH/'''%  mݻ?`ռ2 ÿ)MJ!'wn5ϟҺA5Ҋl|-6?y/>S vHa( q, { 5#g8";E-/EIJ(&4/'*+"! 4/&:E_A,T15`-2G8a82`- |8G5t tGl BQ{+"[9#55>32~E O w)3;?;V%Q )?2@~S1CJ>'w),*o#( c. go qB* L$E,9٪!/cטwnֿ$ѰOK ˿Ą`hNIl߶[L^,$&* 2:D- W))|8@<t ܠW2I)o$)W0z63&%#%+-?2u'WL!pQd ;E=lT#c$I= /ٓ٘z_ˡĆ6 .+̟<îIߢ߽"Co2QߟvYeQ a,2J& 8);w] YjJ ~üdsϹ5.%mˬiݝL cQ'ӷ( w~T(>>t27,T.7@F4QK{L=;M369\4*F"HH8>^ 1>AaCk@1j OMJ{ 6W \ @V'"x%ti݇߰%d'q@ ǽܘgvB?ơɓ|R/l߬$HΓ/όׇ͘oj M 2%x 8I` Q G"  G" $X\%tڇ?(Q .55.)|-w49\42(!&( Q &%/  %(Wq.24E"QD+@8 *  { T# "GX6  WnCGX]G/Xؠ O c;3nӬ3hE W,.[!!% jHG T   /t,QE׳D՛glLIk]*<6~M j kI B z;W  ,$(&!>~GY2(-$gpS tYB *c$T#~B~t)3/8%2'Wzgj , x  1t  e "lg۸6  L. Q,OO 2[ `""vHB~aS kGte} = ۿK=E)սߌ @[q/٢?1nUŐ0ܳup;S*`1>o %5*)+4 E !  g %.[!$q^ -$&`"7!(.-r%a *'H$2`-R!!c. ET#C+#'!  @ 6 $. E  abj aj ')հʽ:tt Y9$5ddҿqv M>xtC,nNݾ S%O>r;8l lQ |Yj O )l  z 2**/%%Oq]jtJyc %#2"( gY lkyv8%,~Gv E veYok6  j `W0\)4 ,G"2;@.}o=e#m!e1.1 *  gmtSbBQI,6EQvILO Ӂ [Gx|4 IEWQ 9%"4 x [vQ߉5dS dx`|8Hg  SM]2 q2 c$# { ] . ol ,O  #*<%!.T"y ,{ X4 G;4 p~^ e* QB,q 2e>tH[Q! "* Lo Q M,{ v'bYjS   t. l tJ%T.4!5*V%Q B yBBEy 8e5I e&%6tC4vT,t*#5 et`2  Xx]M^Q6 tQQ"~Ib4El6Og{ agnv6.oEc lE a`n>[.1$VccH@x =/ =x  x ;  O G"o G5([XQ JH   *~"4J%@/c( Y GO 1h=* $5; 5y*.g` w4Hz  #e%2'weVyb~vq( ,I  @ H1)B;4OT@.? ;jr;;O88 ( cg, >j $O x 8 }[  y~ ( j tgX IQ` l ( * E %{  ~* Lt^,^~E GE`@S t^8>c TOT 6x1<= ` O v Y*,yQ,EEEa2ety^va  Qv|#m;JE (#Q ] 6 M ,S { 12j Xt  MTY22@4 ImEx[5x { E[, 8 l (q )*vxo#, @  p [ GE 5Wy S C  ej ,; 6x}wTWM ByS8 k[xhyw q S  )*[  4v@<^~( H y~Ml ev "|YMwlB%c4 S`"4 MvT  /""Q e 4 v "j v ko(Mj  a~w 2azy. ==2oH%bgt cY<^Sg( * ` 5,5b,kqz`(B4Bl "BtkE Qwx2oQt; vE  wCY`hYb8.y;g ~G bo( ["pS  }X)e>)Gtn$=8ln,  W2y`Gt  Y  l Q; / Q^ O@EJl[@8E Gg1)B$  %(^@8,;,H2 }~[o q@GdV( 25a 8gO , G E =W>[q8 p/>( Xy~6 a5 @ z B g5px ` ,$>`X1 =tM B @lI . @Gn@X #nB@ 2(  O(k QHkoHO ,;.kv>ckB@ oc 8,Qo8mtbQ>[ =W2^ twb5EQy^ t 5[=p^ VtS4 *   EwkX j 8; .`l {  M`d^GO ( z,>5~4 G,z`nV*gnp)w Sz 1H[ES>YW>qcQB)4zq/BE(Syzkq#@d}I.52`(Mc(bYBz22v zS5z MGSn(O5X W O { l O@^bg dX [(nEMc( T8 `  2mH[%[TwOeW>//2Y2O5544CEg@>b)8)bQMO>d$$(e%z5t(>k ~ .G>~g%,v2l *  @V "] x  n  yl}[b[EtHc@B GMt#t@`1#[wq8/BG^gtcJJn;@ J@E@Yg )l /q O[(QQ(@4,t2I%#QeW> }[>([OSQ`)kk`88 S5@2w,M^ck $}(8%% 8)^I. 2)l ((J4B>o2OBz /8` Q8|JMO x `GdlS5>w YwE5M Qg)blg(c;"=.` , E."gGnlbzEG.;QVy8^2E5y8`y(GE "E,"pw;5BGp8;b(@4))[O q8k%B^Y/TJ#e W%n E`O O% G8O))`5 44,t2y GI.}QOyEz>Y ^(O@ =n([ EQnn8n)Edb`;,E8}dB,Vw8MO88t%yBb)/^B@^y kl,2ggtJ##e ##/ec/wq`l n,=" }XX.I=g.),p.=n}8SG;wBQ58;k)y@We  4`^8,l` QQyk%#Y^%z,Q[z%Mg@ y)lQG)ywSp,}54(,`)pnt=B ;bEQzVE58p;z@>}`b `4zlQ`l8El5,nQl)I)5EzBBlM QEz)(5((k4^B4 g(z> Ql@%[O[^ @2%(B2YE E/@ wMO>e2( H t(2kE)QQ``5,b8GnEz);,"nzS.E`zQBS44BtMy[ SEz5kk@4^Q#ekl 4 (B^y @[^`5M[@2Y52Et84%55pl,z58S)[kB5Ow)zQ)5%OGXEg88 5zVSBES,,E8S)SV,GInl 5zkO^`n`y)n8 OBQykEzlzk>WJy)BBk/#[Q%M^E4 k2z4n)E ;nz,}p88,,BkS8n(y O5lBk((BQ5 (%Qk^ BO5Q(B((kBB4%^ y^4B5QQ( Q(Ez5O``E)BO58tllwB^(twk5z^[w 2yk[k(g#QtzS Q5SS)np^)8Sl(QQ}z l`O`BEzt>^((O (%k^`zyy B^kQQ yMM 5@@ %w5z(5ll^B^zEl)SG^G;88bS}n},E EEl)8znGQByEzz5ESS)5Q5lEEn888``bGnS8)Ezn)n;Gz)n`8) )y5`zl(zn)y 5B (5lQ 5y wkwwkk(k%yw%w% %w B O((w^lyO lyE`5ylEG))8 ```l54OlOk4lOlkw4QByQyy55Q5Byk(^B( kEElykkO^ ((By^kw^BQl)Ql5`^zz)QQBO 55lQ( @Q4 (MOOkk^ 44O^E`E5b5lE`5SS}}8nEnn,zbQ5))QQ`bBk^y4%@ 5^ ^ B ^55yk`8)zBlyklyE)w [k5)BOyz`nn5)`)z;EQQzznnG}5^ESSB(( Ez4 (k(^y^(55ylE4B5QQlly^E8y5Q^ )Ek^BEO4B(^l^ BlO (l O4(nll5 8SB4wwk(y5QyB^Byy^^ 5OO(()B4O 5SS`)`zzn8E`l))55Qz5(^444wwkB^ OO[M2g[w2t>M [[w gM 2wkOg@OOkO[[O B^^ @ ^( BQ)Q55B^yEl5EQ)zSl)G,8`zz)Sz)`8E`)zE`lE```5l)55l[( kyQB^Bk[y4yy 44O(^^yOk5B BQ^yyB( yy^EElQQ5l((y5`8n855`z)`8nSSnGbG}G ;;pnpV}nSnbSzz5zB B(BQ5 4O^yk4^ [%w%gM MM kwkw@ %O[ggOk(y^O (^ BBl l(kO4 ^k 5B(yB ^nzQ5E`z`ESE})z`z)^ ^5y^^ yy(Q(y(44k44 ^B B^^k(O B(ByQy^y(B(BQB QQz8SQB()`zEEl`E`))zEQ`8SSE`)SG,,b,GGnzS8SS8S)z)Ql555y((ly ^ll O(5))5^^))^^BByy(^5Q(y5Q(kk B(4O((k4k^B B^BB(y5Q5l)``))z`EQE`)^yllQ5^Byy^^BOO4OkOO[[@w4wO@%w[ %4@M4[[@@% k[ %w%%[ww[M>[%[k((ww% %O44OO4^(O4k(((By B(^(``55QEEzz`zEGG8``E5)Ey By kykk(BOO[www(4O(y( y5 (yQlQlE`)Q5QlQlQ^5Q^ (yyy( (y55QQQ`EQl`))E8S88n,nnnnn,GGn,}}bb},nS,)zS`Ez`Q5Qll5555QQ y ^y^y( B k(((yyyy y((^B( B((yQl5QEQl`El555)QQ)EQQ)`EQ))E))S88nzzz)`zl5Q55yB5Q^ k 4 BOw[y(kkkkO[ @O4(Bkkk4(yB 4BBOOkkO kk(^ ((B^^B^5(B5ll^yyy55ll5l`)lQEQ5QQ5l55l555BBl5B(y^^^y (Bylyl5^( Byy^B((yBO4k (BBB kOkO(4OkOO((^yyB5ll555l`z`n88EzzE`E)`n`))EE)E8`)z5lll)Ez))`z`)QQQ55`)lQ5lElllQlQQlEQlyy^^l((By^5( yy^B^yO44OO4[[w[[wwwk44B kOkBB(yyB())Q5QllQ)Q))5^Q^(By^B^yy( ^B BBB yyOQQ5B(( ^^( B^55^B(kOB^^(kk(yB( (y(^QQQllQ5QQl5yy5lQQQQ5Q55QQQQQQllQ5lll5Q55y^(BQ55ll5ll5l)Q)`z`)EElE`)EE)E)55lQlQQ))Q5llE5Q)E)`z`QQQ5)`EQyQ55 ^y5QQ5QQ^lE`E)`E````EE``EzzEzE))`z`QlEEQ^ ^y((yB^B^y^( B^ ^5Q5ll5555l5BBy5B B( (^B B^^^yBBk 5l(yB^^( yy y^By(^( B^( ^(O444kOOBB^((BB (( (^Q5QlQQQyBBB5(ByB( B( (B(B^^^(^yB (k444OO O4OO4kOOk^yBkk(B(( B^((By55^BByyQl5Ql)E)EEEE`zzzE`El5l5QQQlQ5lQQQ555E`EEEzzzS```E`z))Qll55QlQ^(^5Qll5B(^y^Qy^^y^yyBByyyyyy^^El( (5Q555QQQll55ll5QlQ5QQQQ55y^B( B^yyy (kO^^(B^BBBBByyyyy ^QlyBB^QQyyy^^B^yBB( ( OkB(O By^ByyBB((B55Qll5Q555QlQQ5^((yy^yyQ^By^QQ5QQQ5QQQQQ)E)lQllQllQQ55QQy55yyy^BB^yyB^yy(^55QQyB (Qy5lQy(B5yy55Qll55QQ5llQ5yy)`E)QQll)EzzEE))E)l5lQQ55555^BB^y5Q5BB5Q5Q5lQQlQQ5QlllQQllQ55Ql5QlQ5Q5^ (^y^(ByyBBy ^^B Byy^yy^B^^yyy^y^^B^yyyyy^^yyQQy^Ql5QlQQQlQ5lQll55Q5y^^^ (BB kOkkOO4Ok4Ok4kBBB (^( ( ( (((BB^BB( (^( B ^BBB(( (((BB (B^yyy555llQ55ll5l)Q5QllllQEE5Ql55Ql555yy^5Q55QQ5Q55Ql55Ql5llQ)lllQl)`lQE`zElQQlQllQy(^^yy (((( (( (( (B^^((BBy^^BByyB^yQ5^y55lQy5555lQ5^B^^yBByyByll5lB^yyB((^^^By^( ((B( (B^B ((B^( Byy^yyy55Q55lllll55QQQ555y^BBy5QllQQll5Qll5QlQQQ555Q555Ql5QQQQllllllQQQ555Q555y5QyyQl5QQQQ5l55Q555QllQQQQQQllllQQQQlQ55lllQQlQ5^B(yBB^^^yyy^(yy( (B^yB( ^^^^Qyyyy^y^^^55^^yyBBB^B( (BB^B ( (( kO4k^^( ( BB^^y^^B( (By^^B^yQl55QlQ55555QQ5555QQll5Q5Q5lQl55555ll))`)))EzD  Nhh33MMM222L///..v^FFuuEE.E\E\-DDDD---qZCYC,*AA**@@)SSS?(>>S>>>((='eeQ'&&&&%$$6twxxyyyYH8IZ{||lmmm~    &    "!!!!!  $$$                 LISTXINFOINAM SD-AmbiHopISFT8Awave Studio v7.0, Copyright 1993, 2000 FMJ-Softwaresmpl<X<Cchuck-1.2.0.8.dfsg/examples/data/snare.wav0000644000175000017500000003233010600421722016716 0ustar piempiemRIFF4WAVEfmt DXdata 4.u; d>C[](`1a;TgҺ hI7Bd) ضHPcvm*M4 VK+ݠ+ĭr'9Ʒl=p"fEmUNZ@&gQ,q={f44 rxA]Vw(@Go_j*lW!$ȠI%㳚E='4ׄn#m[ݷ7{>CS2G:E0> Kt&ې!& _PT ߿YT߻ŭ~,q# ZV , G9Sʸ#޼*R ڬƸEv= 78   ٿ GS*A/\UdB1"(IEMƧjY* L)2[Kn u/i6GҦԡև-D!U1Ee?Ę=2P0!qDM._\l"=5%WSۦ*?J. ZLb4}Z131z@4::U> P12:!E nZ+aEy51(6[d biyYpDDw- OwA) #n,(!*ݷCt6Kx t[#@ Ia-@F#}|)⻬H^ZDb< Ċ͍(f6(̋ N-օ!)ڴֽЋ 8$o9/SJ)4 S*!,K)$:8 3Է  D6}73Rb\UP!L+|5p>5: <|۔ 3Aܲ/LWQ& $7lܸIsI_eZk۝ϙi ';)sd TռW )ՔDʺ t&65(5,%%!B4y`u@2'k=k=(("KAN% =<[rF|V.,*1 J&z -*) vtX1!% z f F o$gѧU(LR}&ꓭw^ `f܇unH> ܈-݄ewb2y @:wg:Lۗ*I +տ* 1k 7܆3; J y #M= H7f3+ Jz"]  N2l :9'R.,\/8j66=c7#H "Y0ּ,е֙+4ɲ76sg ё>ј yH"../e0*F ,c3#A2n+N DcL ']!*^ l +d #%P< 1/DLkjM- Xk+ V)W/%$Ul,% dL{L2 C s* x> mm ".P2nTeEEp0ds=P)+[T L @#e5y& D &@\*#+? Z &3q#N Dh7E Oߓ23N4 aBf/Dt`k{M p] ,X .8L# z '| +>y? r4 Ix!wUi0s3y</g 'r< G 'e  `A3+ S; sND' ! &p  jt M Zwde{ ']_0c J) ujJK c7)A wbU\  mNZ`K cߥ0 !2Ucr *  !  i 4L  3"#PW h)t\:,S- 0a T0 _/'% v+^'Q E Y_hj h4D VktJFKO޽2ߎRU  p P ^@ "V{ D ZuG d1 CfV?   vlz;f E/ z "M ;?>^|[B?Gszd;m~HQYޘ9Ex| g*X+PQnOH^2=" #> bE !u  qZ^;u-*X  - ~RQ fTvic ] |K tS&U~H~1  |>yE*x5.H2 RmXD{0d|G 6 F e  /  9$nq zEPQ E6fZ)M).T* @](om9  ~@ lh`K] zN 8 ]  %q)+ e#/aMz Y Ed\ t!=[$h[n>k@ [*+  G + CmAQH v 0 Xe O" U9, 4. gnL[]OY7i~1U7 Y \q!JWmQQP:0X?-.` 8= 8 ~r^E9 q  >z<  ;vx # Z ~ \ 1z /?5#p1 3Mk1P,P6 Y5LD7MF[#tEX,L9_XV`$9u :]Q^^_ (G6 B]"m \% "  2"* 5G/v]O BQ3 ZWbm^AoQ` ]A>b0P~mF/tI Xd!@ !F;i { % @    Po U 9 0 RjP l~ n!0 (x:o H( o,P:nc#t[!7^v pp'7W& LF /^[.Fsc  z@IIH9fw Y 9 B #!5 i({En`yGJaM5I  >zVr+5SP2[   v mW?3)1z[;?Mi%K*VDJiq=QzU-l~,eRF3l$ :nt-7[KrbG {! X 5c $(G7iq \[GHL }*kt4 gC~fD^KE@uK9hK5;_' Gpm,Kd*G@?6u 24c"W ijQ*A H) >p4 (Fosh7  }mA hr{tEMn 5:0n44^g4.tv >5i-5]-6!SQFWY'2{ A"4nK D{*{47{PA z LXs5YZH\8mE/_QW^~2P\\5dq6*;h 2-d?D"!^KgtkjV| )4!=Tc58>ol &d9nZc"q "k b0*S9+rE45]$e"LXPaS$*-j[0 l]mc?hay$$%M;SUmVW;FI(q!pPDB1v66h5?6MmtI8S*4#e\)(m\K;mOVjbb0j?{pwx5;Ym5pb/iP/d@/%Pyj~a -bBx(Q4A{"e.LJ6*\9 |(F5hM"JSXFlT.p$d%G*g%W$U{c6lPdKO\$RvYpUQyWt%a^|Hge\ [FD.BF2@KkJJ*EjQ'%Ns=Anj$F( -EBb^Fg@t>ePyeWn~);B|_ vqr2S2 1rie@d.Gy334c dD^"zVS!dS@pv4R [i~W/hpPB'_?VrXDi@QD$Su-8K\D4LU4 dSMTS: D7uV:i{V~v;B~XP @NXajHHH~8M<_D?W,S&PM5 i_: ~ ?U cWPxUJ)b-a;xg#F]"XE%iFP[Ttt K#[!GhFq]As2TP\']perS(hz'v@aG.Vtb2cQY/t.V@V PHX3|o.bA5GM[yF% k43}.9c:.nLQA5~FUdad0 maP\]E|[mY|tH0<ue_:$Q5+V3MPiXpu+7_L+>9D\ndcD1kM0G:j%~UdPuqN2LagEB KS:3)P#-#en2 ,"k.j8!>nANK%: ey k_G;$0R0\Me2Hi+ n2gLOE$(4N]m@vHAjPs5(uyWU*8_LW*d?p|@Up/h Kye?p\;*@'6U]M6a)A$>*[ gXOAnie3LY uB?_9xztb3g|^nA+Ygbxt]]P:v:gi4XDhPaG4uuctg!;.8p0Qy) @s9h@UoR\B $L<(Uu{R3S)i PHye;/mbR _MAFm<]v(FdW]v P@SQFm?-J9(>P{;hgJc94\|v boD]p!XH?6M%;93 Au(gMi?sGRhGAzqce6NOK:{u-?p0#i'~<6M 3"( ^iD]XJt|>Uc:D2%5[:a?j%M%""t0D3M%Dx<HNiB-Nto\o?F!:/xd{#BXie3JH[p p;BE jaa<3o3:muU'S9/~xELa|X^[ ^@GE(jO/~|g$VH"@m /Uy+*S)(*86.Q<WMn [z.i~5_~#p6 : 4QoMn *RXtr6tUL_:!k+-@QKsaiVyuLq  |]L#08V*hu96u;;AHAEtB[\EdWH"e~00e[^6zS2HY.Q+SccHV* 3d<hW?kX \"mDinj#jbNx~!N+d:G504YLBF6:eHm #\a Ya[mkB'aW9P8c3b9 ?!oFMvA99[mFQGYya<yjN\8/g?'q/h{V K*Y ypQA8(-] uknxB2(<)%y-3%M{$!>W~-"$y*9|{< \#P-B98 9i'9R9z+3^[(Y0be0j|J!SyhW6nA*3<Wsmpl$X<LISTXINFOICRD 1996-01-01IENG Tony ScharfINAM VirusSnare6ISFTSound Forge 4.0chuck-1.2.0.8.dfsg/examples/deep/0000755000175000017500000000000010600421722015072 5ustar piempiemchuck-1.2.0.8.dfsg/examples/deep/dither.ck0000644000175000017500000000273410600421722016676 0ustar piempiem// dither.ck // demo of dithering // // can use any UGen as source in play_with_dither() // qbits : number of bits to quantize to // do_dither : whether to dither // // gewang // patch Impulse imp => dac; // sine wave generator SinOsc s => blackhole; 220 => s.freq; // go play_with_dither( s, 2::second, 6, false ); play_with_dither( s, 2::second, 6, true ); .5::second => now; play_with_dither( s, 2::second, 5, false ); play_with_dither( s, 2::second, 5, true ); .5::second => now; play_with_dither( s, 2::second, 4, false ); play_with_dither( s, 2::second, 4, true ); .5::second => now; // dither fun void play_with_dither( UGen src, dur T, int qbits, int do_dither ) { // sanity check if( qbits <= 0 || qbits > 24 ) { <<< "quantization bits out of range (1-24)", "" >>>; return; } // loop float sample; int quantized; (1 << 24) => int max; while( T > 0::second ) { // get the last sample src.last() => sample; // quantize it if( do_dither ) // dither ((sample + Std.rand2f(0,Math.pow(2,-qbits))) * max) $ int => quantized; else // no dither (sample * max) $ int => quantized; // throw away extra resolution quantized >> (24-qbits) << (24-qbits) => quantized; // cast it back for playback (quantized $ float) / max => imp.next; // advance time 1::samp => now; // decrement 1::samp -=> T; } } chuck-1.2.0.8.dfsg/examples/deep/dtmf.ck0000644000175000017500000000172310600421722016346 0ustar piempiem// name: dtmf.ck // desc: dual tone multiple frequency // (play this into analog phones to call random people) // author: Perry Cook SinOsc row => dac; SinOsc col => dac; // frequencies [1209.0, 1336.0, 1477.0] @=> float cols[]; [697.0, 770.0, 852.0, 941.0] @=> float rows[]; // if you want to look up by number ( 0 - 9, *, # ) fun int key2col( int key ) { if( !key ) return 1; return (key - 1) % 3; } fun int key2row( int key ) { if( !key ) return 3; return (key - 1) / 3; } 0 => int i; int r,c,n; // go! while (i < 7) { .5 => row.gain; .5 => col.gain; Std.rand2(0,3) => r; Std.rand2(0,2) => c; 1 + r * 3 + c => n; if (n==11) 0 => n; if (n==10) { <<< r , c, "*" >>>; } else if (n==12) { <<< r , c, "#" >>>; } else <<< r , c, n >>>; rows[r] => row.freq; cols[c] => col.freq; 0.1 :: second => now; 0.0 => row.gain; 0.0 => col.gain; 0.05 :: second => now; i + 1 => i; } chuck-1.2.0.8.dfsg/examples/deep/follower.ck0000644000175000017500000000170210600421722017242 0ustar piempiem// SIMPLE ENVELOPE FOLLOWER, by P. Cook /* Hi all. I keep meaning to post to this list about the under-exploited feature that all unit generators have, in that you can cause their inputs to multiply rather than add. As an example, here's a simple power envelope follower that doesn't require sample-level chuck intervention. A gain UG is used to square the incoming A/D signal (try it on your built-in mic), then a OnePole UG is used as a "leaky integrator" to keep a running estimate of the signal power. The main loop wakes up each 100 ms and checks the power, and prints out a message if it's over a certain level. You might need to change the threshold, but you get the idea. */ // patch adc => Gain g => OnePole p => blackhole; // square the input adc => g; // multiply 3 => g.op; // set pole position 0.9999 => p.pole; // loop on while( true ) { // <<< p.last() >>>; if( p.last() > 0.1 ) <<< "BANG!!" >>>; 0.1::second => now; } chuck-1.2.0.8.dfsg/examples/deep/plu.ck0000644000175000017500000000104410600421722016210 0ustar piempiem// karplus + strong plucked string filter // Ge Wang (gewang@cs.princeton.edu) // feedforward Noise imp => OneZero lowpass => dac; // feedback lowpass => Delay delay => lowpass; // our radius .99999 => float R; // our delay order 500 => float L; // set delay L::samp => delay.delay; // set dissipation factor Math.pow( R, L ) => delay.gain; // place zero -1 => lowpass.zero; // fire excitation 1 => imp.gain; // for one delay round trip L::samp => now; // cease fire 0 => imp.gain; // advance time (Math.log(.0001) / Math.log(R))::samp => now; chuck-1.2.0.8.dfsg/examples/deep/plu2.ck0000644000175000017500000000112510600421722016272 0ustar piempiem// plucked string filter, different excitation // Ge Wang (gewang@cs.princeton.edu) // feedforward SndBuf buffy => PoleZero block => OneZero lowpass => dac; // feedback lowpass => Delay delay => lowpass; // our radius .99999 => float R; // our delay order 250 => float L; // set delay L::samp => delay.delay; // set dissipation factor Math.pow( R, L ) => delay.gain; // take out DC and neighborhood .999 => block.blockZero; // place zero -1 => lowpass.zero; // fire excitation (try other sounds too) "special:mand1" => buffy.read; // advance time (Math.log(.0001) / Math.log(R))::samp => now; chuck-1.2.0.8.dfsg/examples/deep/plu3.ck0000644000175000017500000000236610600421722016303 0ustar piempiem// tuned plucked string filter // Ge Wang (gewang@cs.princeton.edu) // feedforward Noise imp => OneZero lowpass => PoleZero allpass => dac; // feedback allpass => Delay delay => lowpass; // our radius .99999 => float R; // finding our (integer) delay order Std.mtof( 80.75 ) => setFreq => float L; // set delay L::samp => delay.delay; // set dissipation factor Math.pow( R, L ) => delay.gain; // place zero -1 => lowpass.zero; // fire excitation 1 => imp.gain; // for one delay round trip L::samp => now; // done 0 => imp.gain; // advance time (Math.log(.0001) / Math.log(R))::samp => now; // set (fundamental) freq fun int setFreq( float freq ) { // sample rate second / samp => float SR; // omega 2 * pi * freq / SR => float omega; // figure total delay needed SR / freq - .5 => float D; // the integer part D $ int => int Di; // the fraction D - Di => float Df; // set allpass using fractional and fundamental polePos( Df, omega ) => allpass.allpass; // return integer portion return Di; } // find pole location from delay and omega fun float polePos( float D, float omega ) { // here it is (a la Jaffe & Smith) return Math.sin( (1-D) * omega / 2 ) / Math.sin( (1+D) * omega / 2 ); } chuck-1.2.0.8.dfsg/examples/deep/thx.ck0000644000175000017500000000354110600421722016217 0ustar piempiem// THX emulatorPerry R. Cook, Jan. 8, 2007 // author: Perry R. Cook (Jan 8, 2007) // modified: Ge Wang (added parameters up top) // F-1, B1b, F1, B2b, F2, B3b, F3, A5, F4, A6 [ 29.0, 87.5, 116.0, 175.0, 233.0, 350.0, 524.0, 880.0, 1048, 1760, 29.0, 87.5, 116.0, 175.0, 233.0, 350.0, 524.0, 880.0, 1048, 1760, 29.0, 87.5, 116.0, 175.0, 233.0, 350.0, 524.0, 880.0, 1048, 1760 ] @=> float targets[]; // storage float initials[30]; float deltas[30]; // parameters (play with these to control timing) 10000 => int steady_samps; 20000 => int sweep_steps; 15000 => int hold_steps; 8000 => int decay_steps; // UGens SawOsc s[30]; Gain gl[30]; Gain gr[30]; JCRev rl => dac.left; JCRev rr => dac.right; // reverb settings 0.1 => rl.mix => rr.mix; // variables 0 => int i => int j; // compute stuff for( 0 => i; i < 30; i++ ) { // random freqs Std.rand2f( 200.0, 800.0 ) => initials[i] => s[i].freq; // 10 sample updates ( targets[i] - initials[i] ) / sweep_steps => deltas[i]; // initial gain 0.1 => s[i].gain; // random Std.rand2f( 0.0, 1.0 ) => gl[i].gain; // panning 1.0 - gl[i].gain() => gr[i].gain; // hook up s[i] => gl[i] => rl; // all the oscs s[i] => gr[i] => rr; } steady_samps :: samp => now; // steady cluster while( j < sweep_steps ) { for( 0 => i; i < 30; i++ ) { initials[i] + (deltas[i]*j) => s[i].freq; // sweep freqs. } j + 1 => j; 10 :: samp => now; } 0 => j; while( j < hold_steps ) { // hold chord 10 :: samp => now; j + 1 => j; } 0 => j; while( j < decay_steps ) { for( 0 => i; i < 30; i++) { 0.1 * (decay_steps-j) / decay_steps => s[i].gain; // decay gains } 10 :: samp => now; j + 1 => j; } 60000 :: samp => now; // reverb tail chuck-1.2.0.8.dfsg/examples/deep/unclap.ck0000644000175000017500000000301010600421722016665 0ustar piempiem// name: unclap.ck // desc: configurable "clapping music" (Steve Reich) // author: Jesus Gollonet (original) // Ge Wang (shreds and glottal pops) // date: Summer 2006 // our patch SndBuf clapper1 => dac.left; SndBuf clapper2 => dac.right; // load built-in sounds "special:glot_ahh" => clapper1.read; 3.0 => clapper1.gain; "special:glot_ooo" => clapper2.read; 3.0 => clapper2.gain; // the full "clapping music" figure [.5, .5, 1, .5, 1, 1, .5, 1 ] @=> float seq[]; // length of quarter note .4::second => dur quarter; // how many measures per shift 3 => int shift_period; // how much to shift by (in quarter notes) .5 => float shift_factor; // one clapper fun void clap( SndBuf buffy, int max, float factor ) { 1 => int shifts; // infinite time loop for( ; ; shifts++ ) { // one measure for( 0 => int count; count < seq.cap(); count++ ) { // set gain seq[count] * 2 => buffy.gain; // clap! 0 => buffy.pos; // let time go by if( !max || shifts < max || count != (seq.cap() - 1) ) seq[count]::quarter => now; else { <<< "shift!!!", "" >>>; seq[count]*factor*quarter => now; 0 => shifts; } } } } // spork one clapper, shift every shift_period measures spork ~ clap( clapper1, shift_period, shift_factor ); // spork, no shift spork ~ clap( clapper2, 0, 0 ); // infinite time loop while( true ) 1::day => now; chuck-1.2.0.8.dfsg/examples/event/0000755000175000017500000000000010600421722015276 5ustar piempiemchuck-1.2.0.8.dfsg/examples/event/ALSO_SEE0000755000175000017500000000020410600421722016452 0ustar piempiem../hid/joy.ck ../midi/gomidi.ck ../midi/polyfony.ck ../midi/polyfony2.ck ../osc/OSC_send.ck ../osc/OSC_recv.ck ../osc/OSC_xmit.ck chuck-1.2.0.8.dfsg/examples/event/broadcast.ck0000644000175000017500000000117310600421722017561 0ustar piempiem// broadcast.ck : event broadcast // delcare event e Event e; // base function for shred fun int hi( Event e ) { // wait on event e => now; // print stuff out <<<"success">>>; } // spork 4 shreds spork ~ hi( e ); spork ~ hi( e ); spork ~ hi( e ); spork ~ hi( e ); // yield current shred (without advancing time) // ... allow other shreds to start running ... // (alternative: advance time to allow all shreds to start running) me.yield(); // signal all shreds waiting on event e e.broadcast(); // advance time since this parent shred will free all child shreds on exit // (alternative: me.yield()) 1::ms => now; chuck-1.2.0.8.dfsg/examples/event/clix.ck0000644000175000017500000000243710600421722016562 0ustar piempiem// name: clix.ck // desc: typing-based instrument, quantized // author: Ge Wang + Perry Cook // computer keyboard input via terminal KBHit kb; // time 4096::samp => dur T; // patch Impulse i => BiQuad f => Envelope e => JCRev r => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // envelope rise/fall time 1::ms => e.duration; // reverb mix .02 => r.mix; // strengths [ 1.0, 0.2, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.5, 0.1, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.8, 0.1, 0.3, 0.2, 0.5, 0.1, 0.2, 0.1, 0.4, 0.1, 0.3, 0.2, 0.3, 0.1, 0.2, 0.1 ] @=> float mygains[]; // capacity mygains.cap() => int N; // total period N * T => dur period; // time-loop while( true ) { // wait on event kb => now; // synch T - (now%T) => now; // loop through 1 or more keys while( kb.more() ) { // figure out period (now % period / period * N) $ int => int index; // generate impulse mygains[index] => i.next; // set filtre freq kb.getchar() => int c => Std.mtof => f.pfreq; // print int value <<< "ascii:", c, "velocity:", mygains[index] >>>; // open e.keyOn(); // advance time T-2::ms => now; // close e.keyOff(); 2::ms => now; } } chuck-1.2.0.8.dfsg/examples/event/clix2.ck0000644000175000017500000000327710600421722016647 0ustar piempiem// name: clix2.ck // desc: typing-based instrument, quantized, multi-channel // author: Ge Wang and Perry Cook // computer keyboard input via terminal KBHit kb; // time 4096::samp => dur T; // patch Impulse i => BiQuad f => Envelope e => JCRev r; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // envelope rise/fall time 1::ms => e.duration; // reverb mix .02 => r.mix; // strengths [ 1.0, 0.2, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.5, 0.1, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.8, 0.1, 0.3, 0.2, 0.5, 0.1, 0.2, 0.1, 0.4, 0.1, 0.3, 0.2, 0.3, 0.1, 0.2, 0.1 ] @=> float mygains[]; // capacity mygains.cap() => int N; // period duration N * T => dur period; // last unen UGen @ last; // total number of channels dac.channels() => int C; // keep track of which int which; // time-loop while( true ) { // wait on event kb => now; // synch T - (now%T) => now; // loop through 1 or more keys while( kb.more() ) { // figure out period (now % period / period * N) $ int => int index; // generate impulse mygains[index] => i.next; // set filtre freq kb.getchar() => int c => Std.mtof => f.pfreq; // print int value <<< "ascii:", c, "velocity:", mygains[index], "channel:", which >>>; // disconnect from previous if( last != NULL ) r =< last; // the dac channel to connect dac.chan(which) @=> last; // the next channel (which + 1) % C => which; // connect revert to dac channel r => last; // open e.keyOn(); // advance time T-2::ms => now; // close e.keyOff(); 2::ms => now; } } chuck-1.2.0.8.dfsg/examples/event/clix3.ck0000644000175000017500000000273510600421722016646 0ustar piempiem// name: clix.ck // desc: typing-based instrument, quantized, multi-channel // author: Ge Wang + Perry Cook // computer keyboard input via terminal KBHit kb; // time 4096::samp => dur T; // patch Impulse i => BiQuad f => Envelope e => JCRev r => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // envelope rise/fall time 1::ms => e.duration; // reverb mix .02 => r.mix; // strengths [ 1.0, 0.2, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.5, 0.1, 0.3, 0.2, 0.4, 0.1, 0.2, 0.1, 0.8, 0.1, 0.3, 0.2, 0.5, 0.1, 0.2, 0.1, 0.4, 0.1, 0.3, 0.2, 0.3, 0.1, 0.2, 0.1 ] @=> float mygains[]; // capacity mygains.cap() => int N; // total period N * T => dur period; // time-loop while( true ) { // wait on event kb => now; // synch T - (now%T) => now; // loop through 1 or more keys while( kb.more() ) { // get char kb.getchar() => int c; // space if( c == 32 ) { <<< "skipping...", "" >>>; T => now; continue; } // figure out period (now % period / period * N) $ int => int index; // generate impulse mygains[index] => i.next; // set filtre freq c => Std.mtof => f.pfreq; // print int value <<< "ascii:", c, "velocity:", mygains[index] >>>; // open e.keyOn(); // advance time T-2::ms => now; // close e.keyOff(); 2::ms => now; } } chuck-1.2.0.8.dfsg/examples/event/event_extend.ck0000644000175000017500000000104510600421722020305 0ustar piempiem// creating custom event objects // new event class class TheEvent extends Event { int value; } // the event TheEvent e; // handler fun int hi( TheEvent e ) { while( true ) { // wait on event e => now; // get the data <<>>; } } // spork spork ~ hi( e ); spork ~ hi( e ); spork ~ hi( e ); spork ~ hi( e ); // infinite time loop while( true ) { // advance time 1::second => now; // set data Std.rand2( 0, 5 ) => e.value; // signal one waiting shred e.signal(); } chuck-1.2.0.8.dfsg/examples/event/kb.ck0000644000175000017500000000036710600421722016217 0ustar piempiem// the event KBHit kb; // time-loop while( true ) { // wait on kbhit event kb => now; // potentially more than 1 key at a time while( kb.more() ) { // print key value <<< "ascii: ", kb.getchar() >>>; } } chuck-1.2.0.8.dfsg/examples/event/kb2.ck0000644000175000017500000000106510600421722016275 0ustar piempiem// computer key input, with sound KBHit kb; // patch Impulse i => BiQuad f => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // initialize float variable 0.0 => float v; // set filter gain .5 => f.gain; // time-loop while( true ) { // wait on event kb => now; // generate impulse 1.0 => i.next; // loop through 1 or more keys while( kb.more() ) { // set filtre freq kb.getchar() => int c => Std.mtof => f.pfreq; // print int value <<< "ascii:", c >>>; } } chuck-1.2.0.8.dfsg/examples/event/signal.ck0000644000175000017500000000076310600421722017100 0ustar piempiem// signal.ck : signaling events // declare an event Event e; // declare function fun int hi( Event e ) { // wait on event e e => now; // this only happens AFTER e is signaled <<<"success">>>; } // spork shred with e spork ~ hi( e ); // yield to give the shred a chance to run (alternative: advance time) me.yield(); // signal e e.signal(); // advance time to let the other shred run // (the parent shred will free the child shred) // (alternative: me.yield()) 1::samp => now; chuck-1.2.0.8.dfsg/examples/event/signal4.ck0000644000175000017500000000116310600421722017157 0ustar piempiem// signal-4.ck : one event signals 4 shreds // our event Event e; // the base function of our shreds fun int hi( Event e, string id ) { // time/event loop while( true ) { // wait on event e => now; <<>>; } } // spork our shreds with different strings spork ~ hi( e, "yo" ); spork ~ hi( e, "hi" ); spork ~ hi( e, "hello" ); spork ~ hi( e, "hey come back here!" ); // may want to yield to give shreds chance to start me.yield(); // time loop while( true ) { // signal one shred e.signal(); // advance time by 1 second (alternative: me.yield()) 1::second => now; } chuck-1.2.0.8.dfsg/examples/filter/0000755000175000017500000000000010600421722015442 5ustar piempiemchuck-1.2.0.8.dfsg/examples/filter/bp.ck0000644000175000017500000000040610600421722016362 0ustar piempiem// our patch Noise n => BPF f => dac; // set filter Q 1 => f.Q; // infinite time-loop float t; while( true ) { // sweep the cutoff 100 + Std.fabs(Math.sin(t)) * 5000 => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/br.ck0000644000175000017500000000051010600421722016360 0ustar piempiem// our patch SqrOsc so => BRF f => dac; // set osc frequency 50 => so.freq; // set filter Q .25 => f.Q; // set gain .5 => f.gain; // infinite time-loop float t; while( true ) { // sweep the cutoff 100 + Std.fabs(Math.sin(t)) * 5000 => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/hp.ck0000644000175000017500000000041510600421722016370 0ustar piempiem// our patch Noise n => HPF f => dac; // set gain .5 => f.gain; // infinite time-loop float t; while( true ) { // sweep the cutoff Math.sin(t) * 110 => Std.fabs => Std.mtof => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/lp.ck0000644000175000017500000000036610600421722016401 0ustar piempiem// our patch Noise n => LPF lpf => dac; // infinite time-loop float t; while( true ) { // sweep the cutoff Math.sin(t) * 110 => Std.fabs => Std.mtof => lpf.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/resonz.ck0000644000175000017500000000041110600421722017275 0ustar piempiem// our patch Noise n => ResonZ f => dac; // set filter Q 1 => f.Q; // infinite time-loop float t; while( true ) { // sweep the cutoff 100 + Std.fabs(Math.sin(t)) * 5000 => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/rhp.ck0000644000175000017500000000050010600421722016545 0ustar piempiem// our patch SqrOsc so => HPF f => dac; // set osc frequency 50 => so.freq; // set Q 10 => f.Q; // set gain .5 => f.gain; // infinite time-loop float t; while( true ) { // sweep the cutoff 100 + Std.fabs(Math.sin(t)) * 5000 => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/filter/rlp.ck0000644000175000017500000000050010600421722016551 0ustar piempiem// our patch SqrOsc so => LPF f => dac; // set osc frequency 50 => so.freq; // set Q 10 => f.Q; // set gain .5 => f.gain; // infinite time-loop float t; while( true ) { // sweep the cutoff 100 + Std.fabs(Math.sin(t)) * 5000 => f.freq; // increment t .005 +=> t; // advance time 5::ms => now; } chuck-1.2.0.8.dfsg/examples/func/0000755000175000017500000000000010600421722015110 5ustar piempiemchuck-1.2.0.8.dfsg/examples/func/func_doozey.ck0000644000175000017500000000137510600421722017761 0ustar piempiem// adapted from Mike McGonagle's bug report class B1 { fun void f(float f[]) { <<< "in B1.f", "" >>>; } } class E1 extends B1 { fun void f(float x, float y, float z) { <<< "in E1.f", "" >>>; } } class B2 { fun void f(float x, float y, float z) { <<< "in B2.f", "" >>>; } } class E2 extends B2 { fun void f(float f[]) { <<< "in E2.f", "" >>>; } } B1 b1; B2 b2; E1 e1; E2 e2; [ 0.1, 0.3, 0.7 ] @=> float myArray[]; b1.f( myArray ); // in B1.f - correct e1.f( myArray ); // in B1.f - correct e1.f( 0.7, .553, 77 ); // in E1.f - correct b2.f( 0.7, .553, 77 ); // in B2.f - correct e2.f( 0.7, .553, 77 ); // in B2.f - correct e2.f( myArray ); // in E2.f - correct chuck-1.2.0.8.dfsg/examples/func/func_obj_arg.ck0000644000175000017500000000047410600421722020052 0ustar piempiem// class with function taking class as argument class Other { 10 => int x; int y; } class X { int x; int y; public void set( Other a ) { a.x => x; a.y => y; } } // instantiate Other a; X x; // call the function x.set(a); // test if( a.x == 10 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/func/func_overload.ck0000644000175000017500000000022010600421722020247 0ustar piempiem// 35.ck : overloading functions fun void foo( int a, int b ) { <<<"success">>>; } fun void foo( int a ) { foo( a, a ); } // call foo( 2 ); chuck-1.2.0.8.dfsg/examples/func/func_overload_member.ck0000644000175000017500000000057510600421722021613 0ustar piempiem// 34.ck : function overloading // declare class class X { // delcare foo fun void foo( int a ) { <<
>>; } // delcare foo with different arguments fun void foo( int a, int b ) { <<<"success">>>; } } // extend X class Y extends X { fun void foo( int a ) { <<>>; } } // instantiate a Y Y y; // call the right one, hopefully y.foo( 3, 5 ); chuck-1.2.0.8.dfsg/examples/func/func_overload_multi.ck0000644000175000017500000000106710600421722021473 0ustar piempiem// func_overload_multi.ck : function overloading fun void bar() { <<<1>>>; } fun void bar( int i ) { <<<2>>>; } fun void bar( string s ) { <<<3>>>; } class X { fun void foo() { <<<"X.foo()">>>; } fun void foo( int i ) { <<<"X.foo(int)">>>; } fun void foo( int a, int b ) { <<<"X.foo(int, int)">>>; } } class Y extends X { fun void foo() { <<<"Y.foo()">>>; } fun void foo( int a, int b ) { <<<"Y.foo(int, int)">>>; } } Y y; y.foo(); y.foo( 1 ); y.foo( 1, 2 ); X x; x.foo( 1, 2 ); bar(); bar(1); bar("a"); chuck-1.2.0.8.dfsg/examples/func/func_recursion.ck0000644000175000017500000000032310600421722020451 0ustar piempiem// recursive function fun int factorial( int x ) { if ( x <= 1 ) return 1; else return x * factorial ( x-1 ); } // call factorial ( 5 ) => int answer; // test if ( answer == 120 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/func/func_void.ck0000644000175000017500000000013610600421722017403 0ustar piempiem// chucking () fun void foo() { <<< "hi!" >>>; } // call foo foo(); // call foo () => foo; chuck-1.2.0.8.dfsg/examples/hanoi++.ck0000644000175000017500000000243210600421722015721 0ustar piempiem// towers of annoy // demonstrates: recursion, arrays, stereo, sndbuf, lame sonification // number of disks 10 => int disks; // min duration for each move 200::ms => dur wait => dur the_wait; // max factor 8 => int factor; // gain to pan to dac Gain g => Pan2 pan; // stereo from here pan.left => NRev r1 => dac.left; pan.right => NRev r2 => dac.right; // set gain .5 => g.gain; // set mix .1 => r1.mix => r2.mix; // the pegs (0 not used - for easy indexing) SndBuf pegs[4]; // load files "data/snare-chili.wav" => pegs[1].read; "data/kick.wav" => pegs[2].read; "data/snare-hop.wav" => pegs[3].read; // connect to gain for( 1 => int i; i < pegs.cap(); i++ ) pegs[i] => g; // the hanoi fun void hanoi( int num, int src, int dest, int other ) { // move all except the biggest if( num > 1 ) hanoi( num - 1, src, other, dest ); // move the biggest <<< "move disk from peg", src, " -> ", "peg", dest >>>; // sonify 0 => pegs[dest].pos; // gain Math.rand2f( .2, .9 ) => pegs[dest].gain; // pan .8 * (dest - 2) => pan.pan; // advance time the_wait => now; // move onto the biggest if( num > 1 ) hanoi( num - 1, other, dest, src ); } // start it hanoi( disks, 1, 3, 2 ); <<<"done!">>>; // let time pass for reverb to go... 2::second => now; chuck-1.2.0.8.dfsg/examples/hanoi.ck0000644000175000017500000000101210600421722015564 0ustar piempiem// towers of annoy : non-sonified version // number of disks 10 => int disks; // moves 0 => int moves; // the hanoi fun void hanoi( int num, int src, int dest, int other ) { // stop here if( num <= 0 ) return; // move all except the biggest hanoi( num - 1, src, other, dest ); // move the biggest <<< "move disk from peg", src, " -> ", "peg", dest, ": #", ++moves >>>; // move onto the biggest hanoi( num - 1, other, dest, src ); } // start it hanoi( disks, 1, 3, 2 ); <<<"done!">>>; chuck-1.2.0.8.dfsg/examples/hid/0000755000175000017500000000000010600421722014721 5ustar piempiemchuck-1.2.0.8.dfsg/examples/hid/joy-fm.ck0000644000175000017500000000351710600421722016447 0ustar piempiem// name: joy-fm.ck // desc: uses first 3 axes of a joystick to control mf, cf, and index for FM // author: Spencer Salazar // which joystick 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // modulator to carrier SinOsc m => SinOsc c => Envelope e => dac; // carrier frequency 220 => c.freq; // modulator frequency 550 => m.freq; // index of modulation 1000 => m.gain; // phase modulation is FM synthesis (sync is 2) 2 => c.sync; // attack 10::ms => e.duration; .5 => e.gain; // variables int base; float a0; float a1; float a2; int count; // start things set( base, a0, a1, a2 ); // hid objects Hid hi; HidMsg msg; // try if( !hi.openJoystick( device ) ) me.exit(); <<< "joystick '" + hi.name() + "' ready...", "" >>>; // infinite time loop while( true ) { // wait on event hi => now; // loop over messages while( hi.recv( msg ) ) { if( msg.isAxisMotion() ) { if( msg.which == 0 ) msg.axisPosition => a0; else if( msg.which == 1 ) msg.axisPosition => a1; else if( msg.which == 2 ) msg.axisPosition => a2; set( base, a0, a1, a2 ); } else if( msg.isButtonDown() ) { msg.which => base; count++; if( count == 1 ) e.keyOn(); set( base, a0, a1, a2 ); } else if( msg.isButtonUp() ) { msg.which => base; count--; if( !count ) e.keyOff(); } } } // mapping function fun void set( int base, float v0, float v1, float v2 ) { // modulator frequency ( 500 + 5*base + ( 500 * v0) ) => m.freq; // carrier frequency ( 220 + (220 * v2) ) => c.freq; // index of modulation ( 1000 * (v1+1) ) => m.gain; <<< "carrier:", c.freq(), "modulator:", m.freq(), "index:", m.gain() >>>; } chuck-1.2.0.8.dfsg/examples/hid/joy-noise.ck0000644000175000017500000000425710600421722017164 0ustar piempiem// name: joynoise.ck // desc: using joystick to control noise (first 3 axes + buttons) // author: Ge Wang // make our Hid objects Hid hi; HidMsg msg; // which joystick 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open joystick if( !hi.openJoystick( device ) ) me.exit(); <<< "joystick '" + hi.name() + "' ready...", "" >>>; // patch Noise n => BiQuad f => Envelope e => Pan2 p => dac; e => Echo echo => p; e => Echo echo2 => p; e => Echo echo3 => p; // set biquad pole radius .99 => f.prad; // set biquad gain .05 => f.gain; // set equal zeros 1 => f.eqzs; // our float 0.0 => float t; // set echo echo.delay() * 2 => echo2.max => echo2.delay; echo.delay() * 3 => echo3.max => echo3.delay; echo.gain( .75 ); echo.gain() * .25 => echo2.gain; echo2.gain() * .25 => echo3.gain; // set gain .5 => n.gain; // attack 10::ms => e.duration; // variables 0 => float value; 1 => float factor; 0 => float q; 0 => int count; // initialize set( value, factor, q ); // infinite time loop while( true ) { // wait on event hi => now; // recv message while( hi.recv( msg ) ) { // axis 0: map to pan if( msg.isAxisMotion() && msg.which == 0 ) { msg.axisPosition => p.pan; } // axis 1: map to pfreq if( msg.isAxisMotion() && msg.which == 1 ) { -msg.axisPosition => value; set( value, factor, q ); } // axis 2: map to Q if( msg.isAxisMotion() && msg.which == 2 ) { msg.axisPosition => q; set( value, factor, q ); } // button down (any) if( msg.isButtonDown() ) { count++; if( count ) e.keyOn(); msg.which + 1 => factor; set( value, factor, q ); } // button up (any) if( msg.isButtonUp() ) { count--; if( !count ) e.keyOff(); } } } // do actual mapping control fun void set( float value, float factor, float q ) { (value * 440 + 480) * factor => f.pfreq; // hacked q mapping if( q >= 0 ) { .99+.009*(Math.pow(2,q)-1) => f.prad; .25+.5*(1-q) => e.gain; } else { .99-.09*(Math.pow(2,-q)-1) => f.prad; 1 => e.gain; } if( count ) <<< "pan:", p.pan(), "resonance:", f.pfreq(), "radius:", f.prad() >>>; } chuck-1.2.0.8.dfsg/examples/hid/joy-shake.ck0000644000175000017500000000254310600421722017136 0ustar piempiem// STK Shakers and joystick! // make HidIn and HidMsg Hid hi; HidMsg msg; // which joystick 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open joystick 0, exit on fail if( !hi.openJoystick( device ) ) me.exit(); // patch Shakers s => JCRev r => dac; .02 => r.mix; int which; // infinite event loop while( true ) { // wait on HidIn as event hi => now; // messages received while( hi.recv( msg ) ) { // axis if( msg.isAxisMotion() ) { if( msg.which == 0 ) (msg.axisPosition+1) / 2.0 => s.energy; if( msg.which == 1 ) (msg.axisPosition+1) * 64 => s.objects; if( msg.which == 2 ) 5 + (msg.axisPosition+1) * 300 => s.freq; if( msg.which == 3 ) (msg.axisPosition+1) / 2.0 => s.decay; //<<< "freq:", s.freq(), "objects:", s.objects(), "energy:", s.energy(), "decay:", s.decay(), "preset:", s.preset() >>>; } // button down if( msg.isButtonDown() ) { if( msg.which == 0 ) s.noteOn( .8 ); if( msg.which == 2 ) { which++; (which % 22) => s.preset; } if( msg.which == 3 ) { which--; (which % 22) => s.preset; } //<<< "freq:", s.freq(), "objects:", s.objects(), "energy:", s.energy(), "decay:", s.decay(), "preset:", s.preset() >>>; } } } chuck-1.2.0.8.dfsg/examples/hid/joy.ck0000644000175000017500000000206610600421722016045 0ustar piempiem// make HidIn and HidMsg Hid hi; HidMsg msg; // which joystick 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open joystick 0, exit on fail if( !hi.openJoystick( device ) ) me.exit(); <<< "joystick '" + hi.name() + "' ready", "" >>>; // infinite event loop while( true ) { // wait on HidIn as event hi => now; // messages received while( hi.recv( msg ) ) { // joystick axis motion if( msg.isAxisMotion() ) { <<< "joystick axis", msg.which, ":", msg.axisPosition >>>; } // joystick button down else if( msg.isButtonDown() ) { <<< "joystick button", msg.which, "down" >>>; } // joystick button up else if( msg.isButtonUp() ) { <<< "joystick button", msg.which, "up" >>>; } // joystick hat/POV switch/d-pad motion else if( msg.isHatMotion() ) { <<< "joystick hat", msg.which, ":", msg.idata >>>; } } } chuck-1.2.0.8.dfsg/examples/hid/kb.ck0000644000175000017500000000135310600421722015636 0ustar piempiemHid hi; HidMsg msg; // which keyboard 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open keyboard (get device number from command line) if( !hi.openKeyboard( device ) ) me.exit(); <<< "keyboard '" + hi.name() + "' ready", "" >>>; // infinite event loop while( true ) { // wait on event hi => now; // get one or more messages while( hi.recv( msg ) ) { // check for action type if( msg.isButtonDown() ) { <<< "down:", msg.which, "(code)", msg.key, "(usb key)", msg.ascii, "(ascii)" >>>; } else { //<<< "up:", msg.which, "(code)", msg.key, "(usb key)", msg.ascii, "(ascii)" >>>; } } } chuck-1.2.0.8.dfsg/examples/hid/keyboard-organ.ck0000644000175000017500000000175110600421722020150 0ustar piempiem// HID Hid hi; HidMsg msg; // which keyboard 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open keyboard (get device number from command line) if( !hi.openKeyboard( device ) ) me.exit(); <<< "keyboard '" + hi.name() + "' ready", "" >>>; // patch BeeThree organ => JCRev r => Echo e => Echo e2 => dac; r => dac; // set delays 240::ms => e.max => e.delay; 480::ms => e2.max => e2.delay; // set gains .6 => e.gain; .3 => e2.gain; .05 => r.mix; 0 => organ.gain; // infinite event loop while( true ) { // wait for event hi => now; // get message while( hi.recv( msg ) ) { // check if( msg.isButtonDown() ) { Std.mtof( msg.which + 45 ) => float freq; if( freq > 20000 ) continue; freq => organ.freq; .5 => organ.gain; 1 => organ.noteOn; 80::ms => now; } else { 0 => organ.noteOff; } } } chuck-1.2.0.8.dfsg/examples/hid/mouse-fm.ck0000644000175000017500000000343310600421722016773 0ustar piempiem// name: mouse-fm.ck // desc: uses first X/Y axes of a mouse to control mf and index for FM // author: Spencer Salazar // which mouse 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // modulator to carrier SinOsc m => SinOsc c => Envelope e => dac; // carrier frequency 220 => c.freq; // modulator frequency 550 => m.freq; // index of modulation 1000 => m.gain; // phase modulation is FM synthesis (sync is 2) 2 => c.sync; // attack 10::ms => e.duration; .5 => e.gain; // variables int base; float a0; float a1; float a2; int count; // start things set( base, a0, a1, a2 ); // hid objects Hid hi; HidMsg msg; // try if( !hi.openMouse( device ) ) me.exit(); <<< "mouse '" + hi.name() + "' ready...", "" >>>; // infinite time loop while( true ) { // wait on event hi => now; // loop over messages while( hi.recv( msg ) ) { if( msg.isMouseMotion() ) { msg.deltaX * .001 + a0 => a0; //else if( msg.which == 1 ) msg.fdata => a1; msg.deltaY * .001 + a1 => a1; set( base, a0, a1, a2 ); } else if( msg.isButtonDown() ) { msg.which => base; count++; if( count == 1 ) e.keyOn(); set( base, a0, a1, a2 ); } else if( msg.isButtonUp() ) { msg.which => base; count--; if( !count ) e.keyOff(); } } } // mapping function fun void set( int base, float v0, float v1, float v2 ) { // modulator frequency ( 500 + 5*base + ( 500 * v0) ) => m.freq; // carrier frequency ( 220 + (220 * v2) ) => c.freq; // index of modulation ( 1000 * (v1+1) ) => m.gain; <<< "carrier:", c.freq(), "modulator:", m.freq(), "index:", m.gain() >>>; } chuck-1.2.0.8.dfsg/examples/hid/mouse.ck0000644000175000017500000000260410600421722016372 0ustar piempiem// make HidIn and HidMsg Hid hi; HidMsg msg; // which mouse 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; // open mouse 0, exit on fail if( !hi.openMouse( device ) ) me.exit(); <<< "mouse '" + hi.name() + "' ready", "" >>>; // infinite event loop while( true ) { // wait on HidIn as event hi => now; // messages received while( hi.recv( msg ) ) { // mouse motion if( msg.isMouseMotion() ) { if( msg.deltaX ) { <<< "mouse motion:", msg.deltaX, "on x-axis" >>>; } if( msg.deltaY ) { <<< "mouse motion:", msg.deltaY, "on y-axis" >>>; } } // mouse button down else if( msg.isButtonDown() ) { <<< "mouse button", msg.which, "down" >>>; } // mouse button up else if( msg.isButtonUp() ) { <<< "mouse button", msg.which, "up" >>>; } // mouse wheel motion else if( msg.isWheelMotion() ) { if( msg.deltaX ) { <<< "mouse wheel:", msg.deltaX, "on x-axis" >>>; } if( msg.deltaY ) { <<< "mouse wheel:", msg.deltaY, "on y-axis" >>>; } } } } chuck-1.2.0.8.dfsg/examples/hid/tilt.ck0000644000175000017500000000134410600421722016216 0ustar piempiemHid hi; HidMsg msg; if( !hi.openTiltSensor() ) { <<< "tilt sensor unavailable", "" >>>; me.exit(); } <<< "tilt sensor ready", "" >>>; while( true ) { hi.read( Hid.ACCELEROMETER, 0, msg ); // x: positive to left of user, negative to right of user // y: positive towards user, negative away from user // z: positive up, negative down <<< "acc x:", msg.x, "acc y:", msg.y, "acc z:", msg.z >>>; // theta: positive in counter-clockwise rotation in x-z plane // phi: positive rotation clockwise towards user y-z plane <<< "theta:", Math.atan2( msg.y, msg.z ) / pi, "phi:", Math.atan2( Math.sqrt( msg.z * msg.z + msg.y * msg.y ), -msg.x ) / pi >>>; .25::second => now; } chuck-1.2.0.8.dfsg/examples/midi/0000755000175000017500000000000010600421722015077 5ustar piempiemchuck-1.2.0.8.dfsg/examples/midi/gomidi.ck0000644000175000017500000000113410600421722016665 0ustar piempiem// number of the device to open (see: chuck --probe) 0 => int device; // get command line if( me.args() ) me.arg(0) => Std.atoi => device; // the midi event MidiIn min; // the message for retrieving data MidiMsg msg; // open the device if( !min.open( device ) ) me.exit(); // print out device that was opened <<< "MIDI device:", min.num(), " -> ", min.name() >>>; // infinite time-loop while( true ) { // wait on the event 'min' min => now; // get the message(s) while( min.recv(msg) ) { // print out midi message <<< msg.data1, msg.data2, msg.data3 >>>; } } chuck-1.2.0.8.dfsg/examples/midi/gomidi2.ck0000644000175000017500000000223110600421722016746 0ustar piempiem// opens MIDI input devices one by one, starting from 0, // until it reaches one it can't open. then waits for // midi events on all open devices and prints out the // device, and contents of the MIDI message // devices to open (try: chuck --probe) MidiIn min[16]; // number of devices int devices; // loop for( int i; i < min.cap(); i++ ) { // no print err min[i].printerr( 0 ); // open the device if( min[i].open( i ) ) { <<< "device", i, "->", min[i].name(), "->", "open: SUCCESS" >>>; spork ~ go( min[i], i ); devices++; } else break; } // check if( devices == 0 ) { <<< "um, couldn't open a single MIDI device, bailing out..." >>>; me.exit(); } // infinite time loop while( true ) 1::second => now; // handler for one midi event fun void go( MidiIn min, int id ) { // the message MidiMsg msg; // infinite event loop while( true ) { // wait on event min => now; // print message while( min.recv( msg ) ) { // print out midi message with id <<< "device", id, ":", msg.data1, msg.data2, msg.data3 >>>; } } } chuck-1.2.0.8.dfsg/examples/midi/polyfony.ck0000644000175000017500000000405010600421722017274 0ustar piempiem//------------------------------------------------ // name: polyfony.ck // desc: polyfonic mandolin model // // by: Ananya Misra and Ge Wang // send all complaints to prc@cs.princeton.edu //-------------------------------------------- // device to open (see: chuck --probe) 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; MidiIn min; MidiMsg msg; // try to open MIDI port (see chuck --probe for available devices) if( !min.open( device ) ) me.exit(); // print out device that was opened <<< "MIDI device:", min.num(), " -> ", min.name() >>>; // make our own event class NoteEvent extends Event { int note; int velocity; } // the event NoteEvent on; // array of ugen's handling each note Event @ us[128]; // the base patch Gain g => JCRev r => dac; .1 => g.gain; .2 => r.mix; // handler for a single voice fun void handler() { // don't connect to dac until we need it Mandolin m; Event off; int note; while( true ) { on => now; on.note => note; // dynamically repatch m => g; Std.mtof( note ) => m.freq; Std.rand2f( .6, .8 ) => m.pluckPos; on.velocity / 128.0 => m.pluck; off @=> us[note]; off => now; null @=> us[note]; m =< g; } } // spork handlers, one for each voice for( 0 => int i; i < 20; i++ ) spork ~ handler(); // infinite time-loop while( true ) { // wait on midi event min => now; // get the midimsg while( min.recv( msg ) ) { // catch only noteon if( msg.data1 != 144 ) continue; // check velocity if( msg.data3 > 0 ) { // store midi note number msg.data2 => on.note; // store velocity msg.data3 => on.velocity; // signal the event on.signal(); // yield without advancing time to allow shred to run me.yield(); } else { if( us[msg.data2] != null ) us[msg.data2].signal(); } } } chuck-1.2.0.8.dfsg/examples/midi/polyfony2.ck0000644000175000017500000000414110600421722017357 0ustar piempiem//------------------------------------------------ // name: polyfony2.ck // desc: polyfonic clarinet model with midi input // // by: Ananya Misra and Ge Wang // send all complaints to prc@cs.princeton.edu //-------------------------------------------- // device to open 0 => int device; // get from command line if( me.args() ) me.arg(0) => Std.atoi => device; MidiIn min; MidiMsg msg; // try to open MIDI port (see chuck --probe for available devices) if( !min.open( device ) ) me.exit(); // print out device that was opened <<< "MIDI device:", min.num(), " -> ", min.name() >>>; // make our own event class NoteEvent extends Event { int note; int velocity; } // the event NoteEvent on; // array of ugen's handling each note Event @ us[128]; // the base patch Gain g => JCRev r => dac; .1 => g.gain; .2 => r.mix; // handler shred for a single voice fun void handler() { // don't connect to dac until we need it Clarinet c; Event off; int note; // inifinite time loop while( true ) { on => now; on.note => note; // dynamically repatch c => g; Std.mtof( note ) => c.freq; .4 + on.velocity / 128.0 * .6 => c.startBlowing; off @=> us[note]; off => now; c.stopBlowing( 10.0 ); null @=> us[note]; 100::ms => now; c =< g; } } // spork handlers, one for each voice for( 0 => int i; i < 20; i++ ) spork ~ handler(); // infinite time loop while( true ) { // wait on midi event min => now; // get the midimsg while( min.recv( msg ) ) { // catch only noteon if( msg.data1 != 144 ) continue; // check velocity if( msg.data3 > 0 ) { // store midi note number msg.data2 => on.note; // store velocity msg.data3 => on.velocity; // signal the event on.signal(); // yield without advancing time to allow shred to run me.yield(); } else { if( us[msg.data2] != null ) us[msg.data2].signal(); } } } chuck-1.2.0.8.dfsg/examples/multi/0000755000175000017500000000000010600421722015307 5ustar piempiemchuck-1.2.0.8.dfsg/examples/multi/i.ck0000644000175000017500000000053610600421722016062 0ustar piempiem// i.ck : n-channel demo // number of channels dac.channels() => int N; // print <<< "dac has", N, "channels" >>>; int i; // make osc bank Impulse s[N]; // connect to individual channels for( int i; i < N; i++ ) { s[i] => dac.chan(i); // .5 => s[i].gain; } // go while( true ) { 1 => s[i].next; 100::ms => now; (i+1)%N => i; } chuck-1.2.0.8.dfsg/examples/multi/n.ck0000644000175000017500000000052010600421722016060 0ustar piempiem// n.ck : n-channel demo // number of channels dac.channels() => int N; // print <<< "dac has", N, "channels" >>>; // make osc bank SinOsc s[N]; // connect to individual channels for( int i; i < N; i++ ) { s[i] => dac.chan(i); Std.rand2f( 400, 440 ) => s[i].freq; .2 => s[i].gain; } // go while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/multi/we-robot.ck0000644000175000017500000000112210600421722017360 0ustar piempiem// take us to your leader (talk into the mic) // gewang, prc // n channels dac.channels() => int N; // print <<< "dac has", N, "channels..." >>>; // delays DelayL d[N]; // gains Gain g3[N]; // our patch - feedforward part adc => Gain g; adc => Gain g2 => dac; // set delays for( int i; i < N; i++ ) { // feedfoward g => d[i] => dac.chan(i); // feedback d[i] => g3[i] => d[i]; // detune 30::ms + Std.rand2f(-15,15)::ms => d[i].max => d[i].delay; .95 => g3[i].gain; } // set parameters 0.25 => g.gain; 0.05 => g2.gain; // time loop while( true ) 100::ms => now; chuck-1.2.0.8.dfsg/examples/oper/0000755000175000017500000000000010600421722015122 5ustar piempiemchuck-1.2.0.8.dfsg/examples/oper/oper_arith_chuck.ck0000644000175000017500000000057010600421722020754 0ustar piempiem// use a variety of arithmetic chuck operators // to directly modify a value 2 => int i; <<>>; 5 +=> i; // 7 <<>>; 3 -=> i; // 4 <<>>; 12 *=> i; // 48 <<>>; 3 /=> i; // 16 <<>>; 7 |=> i; // 10000 | 00111 = 10111 = 23 <<>>; 14 &=> i; // 10111 & 01110 = 00110 = 6; <<>>; 31 ^=> i; // 00110 ^ 11111 = 11001 = 25; <<>>; if ( i == 25 ) <<<"success!">>>; chuck-1.2.0.8.dfsg/examples/oper/oper_assign.ck0000644000175000017500000000055510600421722017757 0ustar piempiem// 17.ck : partial array // assign 1 to newly declared int 1 => int i; // increment assign i 3 +=> i; // reference assignment Object foo @=> Object @ bar; // (foo bar both reference same object) // declare int array 2x2 int x[2][2]; // assign 2 => x[1][1]; // assign partial array reference to 'y' x[1] @=> int y[]; // test if( y[1] == 2 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/oper/oper_logic.ck0000644000175000017500000000036010600421722017562 0ustar piempiem// chuck logical operators <<<"AND">>>; <<>>; <<>>; <<<"OR">>>; <<>>; <<>>; <<<"==">>>; <<< 2 + 2 == 4>>>; <<< 2 + 2 == 5>>>; <<<"!=">>>; <<< 2 + 2 != 5>>>; <<< 2 + 2 != 4>>>; chuck-1.2.0.8.dfsg/examples/oper/oper_post_inc.ck0000644000175000017500000000023410600421722020303 0ustar piempiem// i++ - doesn't fully work yet (1.2.0.1) 4 => int i; i++ => int j; <<<"printing i, then j">>>; <<>>; <<>>; if ( i == 5 && j == 4) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/oper/oper_pre_inc.ck0000644000175000017500000000016510600421722020107 0ustar piempiem// ++i 4 => int i; ++i => int j; <<<"printing i, j">>>; <<>>; <<>>; if ( i == 5 && j == 5 ) <<<"success">>>; chuck-1.2.0.8.dfsg/examples/osc/0000755000175000017500000000000010600421722014741 5ustar piempiemchuck-1.2.0.8.dfsg/examples/osc/OSC_recv.ck0000644000175000017500000000144010600421722016722 0ustar piempiem// (launch with OSC_send.ck) // the patch SndBuf buf => dac; // load the file "../data/snare.wav" => buf.read; // don't play yet 0 => buf.play; // create our OSC receiver OscRecv recv; // use port 6449 6449 => recv.port; // start listening (launch thread) recv.listen(); // create an address in the receiver, store in new variable recv.event( "/sndbuf/buf/rate, f" ) @=> OscEvent oe; // infinite event loop while ( true ) { // wait for event to arrive oe => now; // grab the next message from the queue. while ( oe.nextMsg() != 0 ) { // getFloat fetches the expected float (as indicated by "f") oe.getFloat() => buf.play; // print <<< "got (via OSC):", buf.play() >>>; // set play pointer to beginning 0 => buf.pos; } } chuck-1.2.0.8.dfsg/examples/osc/OSC_send.ck0000644000175000017500000000132410600421722016715 0ustar piempiem// launch with OSC_recv.ck // host name and port "localhost" => string hostname; 6449 => int port; // get command line if( me.args() ) me.arg(0) => hostname; if( me.args() > 1 ) me.arg(1) => Std.atoi => port; // send object OscSend xmit; // aim the transmitter xmit.setHost( hostname, port ); // infinite time loop while( true ) { // start the message... // the type string ',f' expects a single float argument xmit.startMsg( "/sndbuf/buf/rate", "f" ); // a message is kicked as soon as it is complete // - type string is satisfied and bundles are closed Std.rand2f( .5, 2.0 ) => float temp => xmit.addFloat; <<< "sent (via OSC):", temp >>>; // advance time 0.2::second => now; } chuck-1.2.0.8.dfsg/examples/osc/OSC_xmit.ck0000644000175000017500000000153710600421722016753 0ustar piempiem// launch with OSC_recv.ck // hostname and port "localhost" => string hostname; 6449 => int port; // get command line if( me.args() ) me.arg(0) => hostname; if( me.args() > 1 ) me.arg(1) => Std.atoi => port; // the sender OscSend xmit; // aim the transmitter xmit.setHost( hostname, port ); // stuff 0.0 => float running; 0.0 => float modrunning; 0 => int ct; 0.25 => float res; [55, 57, 55, 58, 55, 59, 53] @=> int notes[]; 7 => int nnote; 0 => int idx; // infinite time loop while( true ) { float f; if ( ct % 4 != 3 ) { Std.rand2f( 0.90, 1.10 ) => f; } else { running - modrunning => float diff; ( 1.0 + diff ) / res => f; } xmit.startMsg ( "/sndbuf/buf/play", "f" ); f => xmit.addFloat; res * f::second => now; res * f +=> modrunning; // actual time res +=> running; // track time 1 +=> ct; } chuck-1.2.0.8.dfsg/examples/osc/r.ck0000644000175000017500000000137610600421722015530 0ustar piempiem// (launch with s.ck) // the patch SinOsc s => JCRev r => dac; .5 => s.gain; .1 => r.mix; // create our OSC receiver OscRecv recv; // use port 6449 (or whatever) 6449 => recv.port; // start listening (launch thread) recv.listen(); // create an address in the receiver, store in new variable recv.event( "/foo/notes, i f" ) @=> OscEvent oe; // infinite event loop while( true ) { // wait for event to arrive oe => now; // grab the next message from the queue. while( oe.nextMsg() ) { int i; float f; // getFloat fetches the expected float (as indicated by "i f") oe.getInt() => i => Std.mtof => s.freq; oe.getFloat() => f => s.gain; // print <<< "got (via OSC):", i, f >>>; } } chuck-1.2.0.8.dfsg/examples/osc/s.ck0000644000175000017500000000127410600421722015526 0ustar piempiem// launch with r.ck // name "localhost" => string hostname; 6449 => int port; // check command line if( me.args() ) me.arg(0) => hostname; if( me.args() > 1 ) me.arg(1) => Std.atoi => port; // send object OscSend xmit; // aim the transmitter xmit.setHost( hostname, port ); // infinite time loop while( true ) { int i; float f; // start the message... // the type string 'i f' expects a int, float xmit.startMsg( "/foo/notes", "i f" ); // a message is kicked as soon as it is complete // - type string is satisfied and bundles are closed Std.rand2( 30, 80 ) => xmit.addInt; Std.rand2f( .1, .5 ) => xmit.addFloat; // advance time 0.2::second => now; } chuck-1.2.0.8.dfsg/examples/otf_01.ck0000644000175000017500000000135210600421722015565 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // construct the patch SndBuf buf => Gain g => dac; "data/kick.wav" => buf.read; .5 => g.gain; // time loop while( true ) { 0 => buf.pos; Std.rand2f(.8,.9) => buf.gain; 1::T => now; } chuck-1.2.0.8.dfsg/examples/otf_02.ck0000644000175000017500000000163010600421722015565 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // construct the patch SndBuf buf => Gain g => dac; "data/hihat.wav" => buf.read; .25 => g.gain; // time loop while( true ) { Std.rand2f(.4,.9) => buf.gain; if( Std.randf() > 0.75 ) { 0 => buf.pos; .5::T => now; } else { 0 => buf.pos; .25::T => now; 0 => buf.pos; .25::T => now; } } chuck-1.2.0.8.dfsg/examples/otf_03.ck0000644000175000017500000000144210600421722015567 0ustar piempiem //----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // extra half T offset .5::T => now; // construct the patch SndBuf buf => Gain g => dac; "data/hihat-open.wav" => buf.read; .5 => g.gain; // time loop while( true ) { 0 => buf.pos; Std.rand2f(.8,.9) => buf.gain; 1::T => now; } chuck-1.2.0.8.dfsg/examples/otf_04.ck0000644000175000017500000000202510600421722015566 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // one period offset T => now; // construct the patch SndBuf buf => Gain g => dac; "data/snare-hop.wav" => buf.read; .6 => g.gain; // where we actually want to start 100 => int where; // time loop while( true ) { Std.rand2f(.8,.9) => buf.gain; if( Std.randf() > -.5 ) { where => buf.pos; 2::T => now; } else { where => buf.pos; .75::T => now; .8 => buf.gain; where => buf.pos; 1.25::T => now; } } chuck-1.2.0.8.dfsg/examples/otf_05.ck0000644000175000017500000000160510600421722015572 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // synchronize to period .5::second => dur T; T - (now % T) => now; // connect patch SinOsc s => dac; .25 => s.gain; // scale (in semitones) [ 0, 2, 4, 7, 9 ] @=> int scale[]; // infinite time loop while( true ) { // get note class scale[ Math.rand2(0,4) ] => float freq; // get the final freq Std.mtof( 21.0 + (Std.rand2(0,3)*12 + freq) ) => s.freq; // advance time .25::T => now; } chuck-1.2.0.8.dfsg/examples/otf_06.ck0000644000175000017500000000176010600421722015575 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // synchronize to period .5::second => dur T; T - (now % T) => now; SinOsc s => JCRev r => dac; .05 => s.gain; .25 => r.mix; // scale (in semitones) [ 0, 2, 4, 7, 9 ] @=> int scale[]; // infinite time loop while( true ) { // get note class scale[ Math.rand2(0,4) ] => float freq; // get the final freq Std.mtof( 69 + (Std.rand2(0,3)*12 + freq) ) => s.freq; // reset phase for extra bandwidth 0 => s.phase; // advance time if( Std.randf() > -.5 ) .25::T => now; else .5::T => now; } chuck-1.2.0.8.dfsg/examples/otf_07.ck0000644000175000017500000000336510600421722015601 0ustar piempiem//----------------------------| // on-the-fly synchronization // adapted from Perry's ChucK Drummin' + Ge's sine poops // // authors: Perry Cook (prc@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // --------------------| // add one by one into VM (in pretty much any order): // // terminal-1%> chuck --loop // --- // terminal-2%> chuck + otf_01.ck // (anytime later) // terminal-2%> chuck + otf_02.ck // (etc...) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // construct the patch SndBuf buf => Gain g => JCRev r => dac; "data/snare.wav" => buf.read; .5 => g.gain; .05 => r.mix; // where we actually want to start 25 => int where; // time loop while( true ) { Std.rand2f(.8,.9) => buf.gain; if( Std.randf() > .5 ) { 0 => int i; while( i < 8 ) { i / 8.0 => buf.gain; where => buf.pos; (1.0/8.0)::T => now; i++; } while( i > 0 ) { i / 8.0 => buf.gain; where => buf.pos; (1.0/8.0)::T => now; i--; } } else { .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; } } chuck-1.2.0.8.dfsg/examples/README0000644000175000017500000000005410600421722015034 0ustar piempiemhttp://chuck.cs.princeton.edu/doc/examples/ chuck-1.2.0.8.dfsg/examples/shred/0000755000175000017500000000000010600421722015262 5ustar piempiemchuck-1.2.0.8.dfsg/examples/shred/machine.ck0000644000175000017500000000107610600421722017211 0ustar piempiem// on-the-fly shred management // this is kind of like using the OTF commands // add / remove / replace etc. // except this is done from code and also can be timed. // (this is also a hack for including other files) // infinite time loop while( true ) { // the path is relative to where 'chuck' is invoked Machine.add( "../basic/moe.ck" ) => int moe; // the operation is sample synchronous 500::ms => now; // replace Machine.replace( moe, "../basic/wind.ck" ) => int wind; 500::ms => now; // remove Machine.remove( wind ); } chuck-1.2.0.8.dfsg/examples/shred/powerup.ck0000644000175000017500000000176610600421722017314 0ustar piempiem// power up! // - philipd // global noise source Noise n; // sweep shred fun void sweep( float st, float inc, time end) { //set up the audio chain n => TwoPole z => dac; 1 => z.norm; 0.1 => z.gain; st => z.freq; //store the time we entered the thread now => time my_start; 0.0 => float my_seconds; Std.rand2f ( 0.94, 0.99 ) => z.radius; // keep going until we've passed the end time sent in by the control thread. while ( now < end ) { ( now - my_start ) / 1.0::second => my_seconds; Math.max( my_seconds * 4.0, 1.0 ) * 0.1 => z.gain; z.freq() + inc * -0.02 => z.freq; 10::ms => now; } n =< z; z =< dac; } // time loop while ( true ) { 500::ms => dur d; if ( Std.rand2 ( 0, 10 ) > 3 ) d * 2.0 => d; if ( Std.rand2 ( 0, 10 ) > 6 ) d * 3.0 => d; spork ~ sweep( 220.0 * Std.rand2(1,8), 880.0 + Std.rand2f(100.0, 880.0), now + Std.rand2f(1.0, 3.0)::second ); d => now; } chuck-1.2.0.8.dfsg/examples/shred/spork.ck0000644000175000017500000000045610600421722016744 0ustar piempiem// this shows how to dynamically spork shreds... fun void foo( int a ) { while( true ) { <<>>; 500::ms => now; } } spork ~ foo( 1 ); 250::ms => now; spork ~ foo( 2 ); // infinite time loop - children shreds leave with parent shred while( true ) 1::second => now; chuck-1.2.0.8.dfsg/examples/shred/spork2.ck0000644000175000017500000000050410600421722017020 0ustar piempiem// define function fun void foo() { while( true ) { <<< "hi" >>>; .2::second => now; } } // spork the function, remember the shred reference spork ~ foo() @=> Shred @ s; // wait for 2 seconds 2::second => now; // remove by id Machine.remove( s.id() ); // wait a little more 2::second => now; chuck-1.2.0.8.dfsg/examples/special/0000755000175000017500000000000010600421722015575 5ustar piempiemchuck-1.2.0.8.dfsg/examples/special/Dyno-compress.ck0000644000175000017500000000271610600421722020664 0ustar piempiem//--------------------------------------| // Dyno demo 2: "Compressor? I didn't even touch 'er!" // Takes a silly little plucked string demo and runs it through a // compressor to enhance sustain. (Ostensibly.) Note that there // are many other (better) reasons to use compressors. // // authors: Matt Hoffman (mdhoffma at cs.princeton.edu) //--------------------------------------| // plucked string, dynamics processor, reverb, dac. StifKarp m => Dyno d => JCRev r => dac; // set reverb params 0.75 => r.gain; 0.01 => r.mix; // set dyno to default compress mode d.compress(); // set release time to be quite long to enhance sustain 2000::ms => d.releaseTime; // set threshold to be a bit lower for more pronounced effect. 0.2 => d.thresh; // set slope (in dB) above the threshold to 1/3 of what it would naturally be 0.33 => d.slopeAbove; // compensate for the gain reduction 2 => d.gain; // set plucked string params 0.1 => m.pickupPosition; 0.0 => m.sustain; 0.0 => m.stretch; // go while(true) { // play a random note Std.mtof(Std.rand2(60, 90)) => m.freq; // twice repeat( 2 ) { // say whether this pluck is compressed or not if(d.op() < 0) <<< "uncompressed" >>>; else <<< "compressed" >>>; 0.5 => m.pluck; 2000::ms => now; // make the next note compressed if this one wasn't, or vice versa -d.op() => d.op; } } chuck-1.2.0.8.dfsg/examples/special/Dyno-duck.ck0000644000175000017500000000257010600421722017755 0ustar piempiem//--------------------------------------| // Dyno demo 3: "Ducker? She didn't even throw a punch!" // Shows how to make one sound fade out when another comes up. This is // probably more often used by radio DJs than electronic musicians, but // what the hey. // // authors: Matt Hoffman (mdhoffma at cs.princeton.edu) //--------------------------------------| // A kick drum that will get quieter when the SinOsc swells. SndBuf buf => Gain g1 => Dyno dy => JCRev r => dac; "../data/kick.wav" => buf.read; .05 => r.mix; // A SinOsc that, when its volume swells, will make the kick drum get quieter. SinOsc s => Gain g2 => r; 220 => s.freq; // Make dy go into ducker mode dy.duck(); // spork the shred that makes the kick kick. spork ~ playKick(); // th is the phase of the low-freq sine that modulates the SinOsc's gain 0 => float th; // make the SinOsc a bit less annoying 0.5 => g2.gain; // loop while( true ) { // modulate the SinOsc's gain Math.sin(th) + 1.0 => s.gain; // send the SinOsc's last sample to dy (manually. yes, this is a pain.) s.last() => dy.sideInput; // advance the modulating sine's phase a tiny bit th + 0.00003 => th; // advance time by one sample. 1::samp => now; } // retriggers the kick drum over and over and over and over and over. fun void playKick() { while(true) { 0 => buf.pos; 500::ms => now; } } chuck-1.2.0.8.dfsg/examples/special/Dyno-limit.ck0000644000175000017500000000403410600421722020142 0ustar piempiem//--------------------------------------| // Dyno demo 1: "Limiter? I hardly know 'er!" // Takes otf_07.ck, cranks the gain up obscenely high, then limits // it so it won't clip. // // authors: Matt Hoffman (mdhoffma at cs.princeton.edu) // Ge Wang (gewang at cs.princeton.edu) // Perry Cook (prc at cs.princeton.edu) //--------------------------------------| // this synchronizes to period .5::second => dur T; T - (now % T) => now; // construct the patch SndBuf buf => Gain g => Dyno dy => JCRev r => dac; "../data/kick.wav" => buf.read; .01 => r.mix; // make gain way too high, i.e. force clipping 100 => g.gain; // turn on limiter functionality dy.limit(); // compensate for the limiter's gain reduction 5 => dy.gain; // uncomment this to turn off the limiter. note that just because clipping // sounds cool here doesn't mean it will in your patch. // -1 => dy.op; // where we actually want to start 25 => int where; // time loop while( true ) { Std.rand2f(.8,.9) => buf.gain; if( Std.randf() > .5 ) { 0 => int i; while( i < 8 ) { i / 8.0 => buf.gain; where => buf.pos; (1.0/8.0)::T => now; i++; } while( i > 0 ) { i / 8.0 => buf.gain; where => buf.pos; (1.0/8.0)::T => now; i--; } } else { .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; .9 => buf.gain; where => buf.pos; .25::T => now; .3 => buf.gain; where => buf.pos; .25::T => now; } } chuck-1.2.0.8.dfsg/examples/special/Gen10-test.ck0000644000175000017500000000117710600421722017751 0ustar piempiem// gen10 sinusoidal lookup table // ported to ChucK from rtcmix by dan trueman // see luke's page: http://www.music.columbia.edu/cmix/makegens.html#05 Phasor drive => Gen10 g10 => dac; // can also lookup table values directly: // g10.lookup(index); // with index:[0,1] // load up the coeffs; amplitudes for successive partials g10.coefs( [1., 0.5, 0.3, 0.2] ); // set frequency for reading through table drive.freq(440.); // infinite time loop while (true) { // advance time 500::ms => now; // nothing needed to do, so lets look // up some random parts of the table! <<< g10.lookup(Std.rand2f(0,1)) >>>; } chuck-1.2.0.8.dfsg/examples/special/Gen17-test.ck0000644000175000017500000000324610600421722017757 0ustar piempiem// gen17 chebyshev lookup table // // ported to ChucK from rtcmix by dan trueman // see luke's page: http://www.music.columbia.edu/cmix/makegens.html#06 // // like gen10, this is a series of weightings for successive partials // also http://www.music.columbia.edu/cmc/Rtcmix/docs/scorefile/gen17.html // and http://www.music.columbia.edu/cmc/Rtcmix/docs/scorefile/maketable.html (scroll down) // for nice documentation of this gen // see also: http://math.fullerton.edu/mathews/n2003/ChebyshevPolyMod.html // for info about chebyshev polynomials in general // // the main feature to be aware of is that these functions are primarily // useful for waveshaping, so in this case we drive it with a // SinOsc instead of a Phasor. see, for example: // http://crca.ucsd.edu/~msp/techniques/v0.08/book-html/node74.html // http://en.wikipedia.org/wiki/Distortion_synthesis // the patch SinOsc drive => Gen17 g17 => dac; // load up the coeffs [1., 0.5, 0.25, 0.125, 0.06, 0.03, 0.015] => g17.coefs; // some examples to try // [1., 0.5, 0.3, 0.2] => g17.coefs; // [1., 0.5, 0.25, 0.125, 0.06, 0.03, 0.015] => g17.coefs; // [1., 0.] @=> g17.coefs; // a simple one // make it quiet 0.1 => g17.gain; // set frequency for reading through table drive.freq( 440 ); // sounds better not going to extremes drive.gain( 0.99 ); // create an envelope to scan through the table values // so we can look at them as well as hear them Envelope e => blackhole; e.duration( 10000::ms ); 0. => e.value; e.keyOn(); // loop while (true) { // print <<< e.value(), g17.lookup(e.value()) >>>; // stop when envelope reaches 1 if( e.value() == 1. ) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/Gen5-test.ck0000644000175000017500000000170110600421722017666 0ustar piempiem// gen5: exponential line segment table generator // probably superceded by CurveTable // ported to ChucK from rtcmix by dan trueman // see luke's page: http://www.music.columbia.edu/cmix/makegens.html#02 // make one, no sound here Gen5 g5; // set up the values [0,1] and distances in the table // first arg is initial value // followed by pairs indicating distance (total distance = 1) // and destination value for exponential segments // NOTE: real minimum value is 0.000001 // the following will create a triangle, with a peak at 1 halfway // through the table [0., 0.5, 1., 0.5, 0.] => g5.coefs; // create an envelope to scan through the table values // creates a continuous input from 0 -> 1 over 10 seconds Envelope e => blackhole; e.duration( 10000::ms ); 0. => e.value; e.keyOn(); // loop while (true) { // print <<>>; // end if( e.value() == 1. ) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/Gen7-test.ck0000644000175000017500000000140410600421722017670 0ustar piempiem// gen7: line segment table generator // probably superceded by CurveTable // ported to ChucK from rtcmix by dan trueman // see luke's page: http://www.music.columbia.edu/cmix/makegens.html#03 // make one, no sound Gen7 g7; // set up the values [0,1] and distances in the table // first arg is initial value // followed by pairs indicating distance (total distance = 1) // and destination value for linear segments // set coefficients [0., 0.5, 1., 0.5, 0.] => g7.coefs; // create an envelope to scan through the table values Envelope e => blackhole; e.duration(10000::ms); 0. => e.value; e.keyOn(); // loop while (true) { // print <<< e.value(), g7.lookup(e.value()) >>>; // end if(e.value() == 1.) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/Gen9-test.ck0000644000175000017500000000206710600421722017700 0ustar piempiem// gen9 inharmonic sinusoidal lookup table // ported to ChucK from rtcmix by dan trueman // see luke's page: http://www.music.columbia.edu/cmix/makegens.html // patch Phasor drive => Gen9 g9 => dac; // can also lookup table values directly: // g9.lookup(index); // with index:[0,1] // load up the coeffs // these are in triplets: // harmonic partial ratio, amplitude, phase // see the RTcmix page: // http://www.music.columbia.edu/cmc/Rtcmix/docs/scorefile/gen9.html // for nice documentation of this gen [1., 1., 0., 2, 0.5, 90., 3., 0.2, 180.] => g9.coefs; // [1., 1., 0.] => g9.coefs; // a simple one // make it quiet 0.1 => g9.gain; // set frequency for reading through table drive.freq( 440. ); // create an envelope to scan through the table values // so we can look at them as well as hear them Envelope e => blackhole; e.duration(10000::ms); 0. => e.value; e.keyOn(); // yay while (true) { // print <<< e.value(), g9.lookup(e.value()) >>>; // end if( e.value() == 1. ) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/GenX-CurveTable-test.ck0000644000175000017500000000177210600421722021773 0ustar piempiem// CurveTable: flexible Curve/Line Segment table generator // make one CurveTable c; // coeffs are all FLOATS, specifying proportional times, values, and curvature: // [time0, value0, curvature to next, time1, value1, curvature,.. // timeN-1, valueN-1, curvaturen-1, timeN, valueN] // times => ascending unitless values (NOT Chuck Time values) // values => whatever // curvature(0) => linear // curvature(<0) => convex // curvature(>0) => concave // see: // http://www.music.columbia.edu/cmc/Rtcmix/docs/scorefile/maketable.html#curve // for more documentation // set [0., 0., -0.5, 1., 1., 0.5, 2., -1.] => c.coefs; // create an envelope to scan through the table values Envelope e => blackhole; e.duration(10000::ms); 0. => e.value; e.keyOn(); //ramp to 1 in 10 seconds // patch Phasor p => c => dac; // set 440. => p.freq; // ready while (true) { // print <<< e.value(), c.lookup(e.value()) >>>; // end if(e.value() == 1.) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/GenX-WarpTable-test.ck0000644000175000017500000000420610600421722021613 0ustar piempiem// WarpTable: end-constrained mapping table // // created originally for the PLOrk Utilities by dan trueman // ported to ChucK by dan trueman, 2007. // // this table is mostly useful for conditioning control signals // it is end-constrained in that an input of 0 always yields 0 // and an output of 1 always yields 1 // // WarpTable.value(0) => 0 always // WarpTable.value(1) => 1 always // // expects input [0,1], generates output [0,1] // // what happens in between is what is interesting.... // // WarpTable is useful for mapping sensors and focusing // attention on: // --either extreme (asymmetrical warping) // --both extremes (symmetrical warping) // --central values (also symmetrical warping) // // the first coefficient sets the asymmetrical warping value // --asym = 1. => linear // --asym > 1. => exponential (focusing resolution on lower output values) // --asym < 1. => log (focusing resolution on higher output values) // // the second coefficient sets the symmetrical warping value // --sym = 1. => linear // --sym < 1. => focusing resolution around central (0.5) output value // __________/ // / // // --sym > 1. => focusing resolution on extremes (0 and 1) output values // _____ // _____/ // // and of course they can be combined to create related warped shapes // make one WarpTable w; // some examples: w.coefs( [4., 1.] ); // fairly strong focus on low values; 4 is useful for octave mappings // w.coefs([0.25, 1.]); // some focus on high values // w.coefs([1., 0.3]); // strong focus on central values // w.coefs([1., 3.]); // strong focus on hi/low values // w.coefs([10., 3.]); // some focus on high values, strong focus on low values; warped // w.coefs([0.1, 0.3]); // w.coefs([1., 1.]); // linear // create an envelope to scan through the table values Envelope e => blackhole; e.duration( 10000::ms ); 0. => e.value; e.keyOn(); // ramp 0 to 1 in 10 seconds // on your mark while( true ) { // print <<< e.value(), w.lookup(e.value()) >>>; // end if( e.value() == 1. ) break; // advance time 10::ms => now; } chuck-1.2.0.8.dfsg/examples/special/LiSa-munger1.ck0000644000175000017500000000433710600421722020327 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-munger1.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // These three example files demonstrate a couple ways to approach granular // sampling with ChucK and LiSa. All are modeled after the munger~ from // PeRColate. One of the cool things about doing this in ChucK is that there // is a lot more ready flexibility in designing grain playback patterns; // rolling one's own idiosyncratic munger is a lot easier. // // Example 1 (below) is simple, but will feature some clicking due to playing // back over the record-point discontinuity. //----------------------------------------------------------------------------- // patch SinOsc s => LiSa lisa => dac; // thru s => dac; // freq params s.freq( 440 ); s.gain( 0.2 ); // modulator SinOsc freqmod => blackhole; freqmod.freq( 0.1 ); // LiSa params lisa.duration( 1::second ); // set it recording constantly; loop records by default lisa.record( 1 ); lisa.gain( 0.1 ); // compute now + 1000::ms => time later; while( now < later ) { // update freqmod.last() * 500. + 200. => s.freq; 10::ms => now; } // record lisa.record(0); s.gain(0); lisa.recRamp( 20::ms ); lisa.maxVoices(30); // <<< lisa.maxvoices() >>>; // this arrangment will create some clicks because of discontinuities // from the loop recording. to fix, need to make a rotating buffer // approach. see the next two example files.... while( true ) { // random Std.rand2f( 1.5, 2.0 ) => float newrate; Std.rand2f( 250, 750 ) * 1::ms => dur newdur; // spork it spork ~ getgrain( newdur, 20::ms, 20::ms, newrate ); // advance time 10::ms => now; } // sporkee fun void getgrain( dur grainlen, dur rampup, dur rampdown, float rate ) { lisa.getVoice() => int newvoice; //<<>>; if( newvoice > -1 ) { lisa.rate(newvoice, rate); // lisa.playpos(newvoice, Std.rand2f(0., 1000.) * 1::ms); lisa.playPos(newvoice, 20::ms); // <<< lisa.playpos(newvoice) >>>; lisa.rampUp( newvoice, rampup ); (grainlen - (rampup + rampdown)) => now; lisa.rampDown( newvoice, rampdown ); rampdown => now; } } chuck-1.2.0.8.dfsg/examples/special/LiSa-munger2.ck0000644000175000017500000000725210600421722020327 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-munger2.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // These three example files demonstrate a couple ways to approach granular // sampling with ChucK and LiSa. All are modeled after the munger~ from // PeRColate. One of the cool things about doing this in ChucK is that there // is a lot more ready flexibility in designing grain playback patterns; // rolling one's own idiosyncratic munger is a lot easier. // // Example 2 (below) demonstrates the rotating buffer approach used in the // munger~ see after the code for an explanation of this approach. presumably // someone smarter than me will dream up a more elegant technique. //----------------------------------------------------------------------------- // oscillator as source // fun scary sounds!!! SinOsc s => dac; s.freq( 440 ); s.gain( 0.2 ); // modulate SinOsc freqmod => blackhole; freqmod.freq( 0.1 ); // use three buffers LiSa lisa[3]; 1::second => dur bufferlen; 0 => int recbuf; 2 => int playbuf; // LiSa params for( 0 => int i; i < 3; i++ ) { lisa[i].duration( bufferlen ); lisa[i].maxVoices( 30 ); lisa[i].clear(); lisa[i].gain( 0.1 ); lisa[i].feedback( 0.5 ); lisa[i].recRamp( 20::ms ); lisa[i].record( 0 ); s => lisa[i] => dac; } lisa[recbuf].record(1); // create grains, rotate record and play bufs as needed // shouldn't click as long as the grainlen < bufferlen while(true) { now + bufferlen => time later; // toss some grains while( now < later ) { Std.rand2f(0.5, 2.5) => float newrate; Std.rand2f(250, 600) * 1::ms => dur newdur; // grain spork ~ getgrain(playbuf, newdur, 20::ms, 20::ms, newrate); // freq freqmod.last() * 400. + 800. => s.freq; // advance time 10::ms => now; } // rotate the record and playbufs lisa[recbuf++].record( 0 ); if( recbuf == 3 ) 0 => recbuf; lisa[recbuf].record( 1 ); playbuf++; if( playbuf == 3 ) 0 => playbuf; } // sporkee fun void getgrain( int which, dur grainlen, dur rampup, dur rampdown, float rate ) { lisa[which].getVoice() => int newvoice; //<<>>; if(newvoice > -1) { lisa[which].rate(newvoice, rate); lisa[which].playPos(newvoice, Std.rand2f(0., 1.) * bufferlen); lisa[which].rampUp(newvoice, rampup); (grainlen - (rampup + rampdown)) => now; lisa[which].rampDown(newvoice, rampdown); rampdown => now; } } /* Rotating Buffer Explanation (from the munger~ source code). the munger~ (and scrubber~) use a rotating three-buffer scheme for creating clickless grains. basically, you don't want to be recording new data anywhere in the buffer where a grain might be playing. so, we divide the buffer into three equal parts (B1, B2, B3). at the outset, let's say: B1 = the recording buffer part (RB) B2 = a part where nothing is happening (QB, for Quiet Buffer) B3 = a part where grains are playing from (PB) let's say each part is N samples long. after we have recorded N sample into B1, we rotate the functionality, so now: B1 = PB B2 = RB B3 = QB why? as long as the grains are guaranteed to be no longer than N samples (adjusted for playback rate) we are assured that none of them will have clicks due to recording discontinuities. we need the Quiet Buffer because when the rotation happens, there may still be grains playing in what was the PB and is now the QB. so, this is a bit cumbersome, but it works. the code here is super duper ugly -- i was learning to code and working out this scheme on the fly, and the code reflects that, but it does work. */ chuck-1.2.0.8.dfsg/examples/special/LiSa-munger3.ck0000644000175000017500000000751710600421722020334 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-munger3.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // These three example files demonstrate a couple ways to approach granular // sampling with ChucK and LiSa. All are modeled after the munger~ from // PeRColate. One of the cool things about doing this in ChucK is that there // is a lot more ready flexibility in designing grain playback patterns; // rolling one's own idiosyncratic munger is a lot easier. // // Example 3 (below) uses the same structure as Example 2, but replicates the // groovy tune munging from the original munger~ helppatch (with pitch // transposition filtering and all!). //----------------------------------------------------------------------------- //oscillator as source SinOsc s => dac; s.freq( 440 ); s.gain( 0.2 ); // play the munger song! Envelope fsmooth => blackhole; spork ~ playtune(250::ms); spork ~ smoothtune(20::ms); // transposition table [0, 4, 7, -2, 12, 15] @=> int pitchtable[]; // use three buffers to avoid clicks LiSa lisa[3]; 1::second => dur bufferlen; // allocated buffer size -- remains static 0.1::second => dur reclooplen; // portion of the buffer size to use -- can vary 0 => int recbuf; 2 => int playbuf; // LiSa params, set for( 0 => int i; i < 3; i++ ) { lisa[i].duration(bufferlen); lisa[i].loopEndRec(reclooplen); lisa[i].maxVoices(30); lisa[i].clear(); lisa[i].gain(0.2); // if you want to retain earlier passes through the recording buff when loop recording: // lisa[i].feedback(0.5); lisa[i].recRamp(20::ms); // ramp at extremes of record buffer while recording lisa[i].record(0); s => lisa[i] => dac; } // start recording in buffer 0 lisa[recbuf].record(1); // create grains, rotate record and play bufs as needed // shouldn't click as long as the grainlen < bufferlen while(true) { // will update record and playbufs to use every reclooplen now + reclooplen => time later; // toss some grains while( now < later ) { Std.rand2f(0, 6) $ int => int newpitch; // choose a transposition from the table Std.mtof(pitchtable[newpitch] + 60)/Std.mtof(60) => float newrate; Std.rand2f(50, 100) * 1::ms => dur newdur; // create a random duration for the grain // spork off the grain! spork ~ getgrain( playbuf, newdur, 20::ms, 20::ms, newrate ); // wait a bit.... then do it again, until we reach reclooplen 5::ms => now; } // rotate the record and playbufs lisa[recbuf++].record( 0 ); if( recbuf == 3 ) 0 => recbuf; lisa[recbuf].record( 1 ); playbuf++; if( playbuf == 3 ) 0 => playbuf; } // for sporking grains; can do lots of different stuff here -- just one example here fun void getgrain(int which, dur grainlen, dur rampup, dur rampdown, float rate) { lisa[which].getVoice() => int newvoice; //<<>>; if( newvoice > -1 ) { lisa[which].rate(newvoice, rate); lisa[which].playPos(newvoice, Std.rand2f(0., 1.) * reclooplen); lisa[which].rampUp(newvoice, rampup); (grainlen - (rampup + rampdown)) => now; lisa[which].rampDown(newvoice, rampdown); rampdown => now; } } // the munger song lives! thanks to luke dubois.... fun void playtune(dur notelen) { 0 => int notectr; [45, 45, 57, 57, 45, 57, 57, 47, 55, 47, 59, 60, 60, 57, 57, 57] @=> int notes[]; Std.mtof(notes[0]) => fsmooth.value => s.freq; while( true ) { //<<>>; Std.mtof(notes[notectr++] + 12) => fsmooth.target; if(notectr == notes.size()) 0 => notectr; notelen => now; } } fun void smoothtune(dur smoothtime) { fsmooth.duration(smoothtime); while (true) { fsmooth.value() => s.freq; 1::ms => now; } } chuck-1.2.0.8.dfsg/examples/special/LiSa-simplelooping.ck0000644000175000017500000000145710600421722021632 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-simplelooping.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // Another simple example of LiSa, demonstrating dopey looping.... //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => LiSa loopme => dac; 440. => s.freq; 0.2 => s.gain; // alloc memory 1::second => loopme.duration; loopme.recRamp( 200::ms ); // start recording input loopme.record( 1 ); // stop recording 1 second later, start playing what was just recorded 1000::ms => now; loopme.record(0); // set playback rate loopme.rate(1.5); loopme.play(1); loopme.loop(1); loopme.bi(1); // go while( true ){ 500::ms => now; } // bye bye chuck-1.2.0.8.dfsg/examples/special/LiSa-track1.ck0000644000175000017500000000264210600421722020133 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-track1.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // demonstrate using track=1 mode with LiSa // // when track == 1, the input is used to control playback position // input [0,1] will control playback position within loop marks // values less than zero are multiplied by -1, so it is possible to use // audio signals [-1, 1] to control playback position, as in waveshaping //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => LiSa loopme => dac; 440. => s.freq; 0.2 => s.gain; // alloc memory 6::second => loopme.duration; 1000::ms => loopme.loopEndRec; 1000::ms => loopme.loopEnd; // set recording ramp time loopme.recRamp(250::ms); // start recording input loopme.record(1); // 1 sec later, stop recording 1000::ms => now; loopme.record(0); // set track mode to 1, where the input chooses playback position // note that you can still record this input 1 => loopme.track; s =< loopme; // disconnect sinosc as input Step i => Envelope e => loopme; // use envelope to control playback position 1. => i.next; // play it forward twice speed 500::ms => e.duration; e.keyOn(); loopme.play(1); 500::ms => now; // now backwards half speed 2000::ms => e.duration; e.keyOff(); 2000::ms => now; loopme.play(0); // bye bye chuck-1.2.0.8.dfsg/examples/special/LiSa-track2.ck0000644000175000017500000000236010600421722020131 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-track2.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // demonstrate using track=1 mode with LiSa // // when track == 1, the input is used to control playback position // input [0,1] will control playback position within loop marks // input values less than zero are multiplied by -1, so it is possible to use // audio signals [-1, 1] to control playback position, as in waveshaping //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => LiSa loopme => dac; 440 => s.freq; 0.2 => s.gain; // alloc memory 6::second => loopme.duration; 1000::ms => loopme.loopEndRec; 1000::ms => loopme.loopEnd; // set recording ramp time loopme.recRamp( 50::ms ); // start recording input loopme.record( 1 ); // 1 sec later, stop recording 1000::ms => now; loopme.record(0); // set track mode to 1, where the input chooses playback position 1 => loopme.track; 0.5 => s.freq; 1. => s.gain; // need to reset gain if we want to get the full loop length loopme.play( 1 ); loopme.gain( 0.1 ); 5000::ms => now; loopme.rampDown( 250::ms ); 500::ms => now; // bye bye chuck-1.2.0.8.dfsg/examples/special/LiSa-track3.ck0000644000175000017500000000243310600421722020133 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-track3.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // demonstrate using track=1 mode with LiSa // // when track == 1, the input is used to control playback position // input [0,1] will control playback position within loop marks // input values less than zero are multiplied by -1, so it is possible to use // audio signals [-1, 1] to control playback position, as in waveshaping //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => LiSa loopme => dac; 440 => s.freq; // alloc memory 6::second => loopme.duration; 1000::ms => loopme.loopEndRec; 1000::ms => loopme.loopEnd; // set recording ramp time loopme.recRamp( 50::ms ); // retain some while loop recording loopme.feedback( 0.99 ); // start recording input loopme.record( 1 ); // 1 sec later, this time DON'T stop recording.... 1000::ms => now; // set track mode to 1, where the input chooses playback position 1 => loopme.track; // this time don't change the freq; scan through zippy quick loopme.play( 1 ); loopme.gain( 0.01 ); 5000::ms => now; loopme.rampDown( 250::ms ); 500::ms => now; //pretty farking scary //bye bye chuck-1.2.0.8.dfsg/examples/special/LiSa-trigger.ck0000644000175000017500000000547710600421722020422 0ustar piempiem//----------------------------------------------------------------------------- // name: LiSa-trigger.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // based on the S.M.E.L.T. (http://smelt.cs.princeton.edu/) envelope follower // trigger program will trigger start and stop to one-shot LiSa buffers. a sort // of triggered delay line, so the delays follow the player rather than being = // static. Success depends on tuning the envelope follower closely to the input // gains on however you are getting audio into ChucK. Mileage will vary.... //----------------------------------------------------------------------------- // patch adc => Gain g => OnePole p => blackhole; // square the input, by chucking adc to g a second time adc => g; // set g to multiply its inputs 3 => g.op; // set pole position, influences how closely the envelope follows the input // : pole = 0 -> output == input; // : as pole position approaches 1, follower will respond more slowly to input 0.995 => p.pole; // thresholds .0001 => float threshold; .00005 => float releaseThresh; // duration between successive polling 10::ms => dur pollDur; // LiSa stuff adc => LiSa lisa => dac; lisa.duration(25::second); // l.gain(0.2); lisa.recRamp(20::ms); lisa.record(1); -1 => int voice; float rate; // read command line args; set rate // be nice to have pitch follower determine this, or some kind of table.... Std.atof(me.arg(0)) => rate; if( rate == 0 ) 1. => rate; <<< "setting rate to: ", rate >>>; // events Event attacks[10]; dur newstarttime, newlen; time starttime_real; // infinite time loop while( true ) { // detect onset if( p.last() > threshold ) { // do something <<< "attack!; starting voice", voice >>>; // play last sample if( voice > -1 ) attacks[voice].signal(); lisa.recPos() => newstarttime; now => starttime_real; // wait for release while( p.last() > releaseThresh ) { pollDur => now; } <<< "release..." >>>; // spork off new sample now - starttime_real => newlen; lisa.getVoice() => voice; if( voice > -1 ) spork ~ playlast( attacks[voice], newstarttime, newlen, rate, voice ); } // determines poll rate pollDur => now; } // sporkee fun void playlast( Event on, dur starttime, dur len, float newrate, int myvoice ) { if( newrate == 0. ) 1. => newrate; <<< "sporking shred with rate: ", newrate >>>; if( rate > 0. ) lisa.playPos( myvoice, starttime ); else lisa.playPos( myvoice, lisa.recPos() - 1::ms ); // wait on => now; lisa.rate( myvoice, newrate ); lisa.rampUp( myvoice, 20::ms ); Std.fabs( newrate ) => float absrate; len / absrate => now; lisa.rampDown( myvoice, ( 250 / absrate )::ms ); ( 250 / absrate )::ms => now; // bye bye shred.... } chuck-1.2.0.8.dfsg/examples/special/readme-GenX.ck0000644000175000017500000000370710600421722020217 0ustar piempiem//----------------------------------------------------------------------------- // name: readme-GenX.ck // desc: old and new lookup table utilities for ChucK // // author: Dan Trueman, 2007 // // These utilities bring the familiar lookup table capabilities of the MusicX // languages to ChucK. They all create an internal lookup table given various // parameters set by the user. This table can then be read at the audio rate // (with Phasor, for example, or any other source) or simply read with .value() // calls. // // A simple example for gen10 is included here. gen10 creates a table of // harmonically related sinusoids; the user sets the relative weights of the // harmonics with an array of floats. The phasor UG creates a continuous // lookup value between 0 and 1 (values less than 0 are multiplied by -1, so // SinOsc and other [-1,1] sources can be used as well). // // All of these other than WarpTable were ported from RTcmix (thanks rtcmix folks!). //----------------------------------------------------------------------------- // patch Phasor drive => Gen10 g10 => dac; // can also lookup table values directly: // g10.lookup(index); // with index:[0,1] // load up the coeffs; amplitudes for successive partials g10.coefs( [1., 0.5, 0.3, 0.2] ); // set frequency for reading through table drive.freq( 440. ); // go while( true ) { 1::day => now; } //----------------------------------------------------------------------------- /* the GenX library includes: gen5: exponential line segment table generator (probably superceded by CurveTable) gen7: line segment table generator (probably superceded by CurveTable) gen9: inharmonic sinusoidal lookup table with ratio and phase control gen10: sinusoidal lookup table *without* ratio and phase control (only partial amp control) gen17: chebyshev polynomial lookup table CurveTable: flexible Curve/Line segment table generator WarpTable: end-constrained mapping table, useful for control signal conditioning */ chuck-1.2.0.8.dfsg/examples/special/readme-LiSa1.ck0000644000175000017500000000220010600421722020252 0ustar piempiem//----------------------------------------------------------------------------- // name: readme-LiSa1.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // the LiSa ugens allow realtime recording of audio to a buffer for various // kinds of manipulation. // // Below is a simple example demonstrating the basic functionality of // LiSa. // // See readme-LiSa2.ck for a command summary and instructions for doing // multiple voice playback. //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => LiSa saveme => dac; s => dac; // monitor the input 440. => s.freq; 0.2 => s.gain; // alloc memory; required 60::second => saveme.duration; // set playback rate 1.5 => saveme.rate; // start recording input saveme.record( 1 ); // 1 sec later, start playing what was just recorded 1000::ms => now; saveme.rampUp( 100::ms ); // use saveme.play( 1 ) to start playing without ramp // hang for a bit 1000::ms => now; // rampdown saveme.rampDown( 300::ms ); // use saveme.play( 0 ) to stop playing without ramp 500::ms => now; // bye bye chuck-1.2.0.8.dfsg/examples/special/readme-LiSa2.ck0000644000175000017500000001001310600421722020254 0ustar piempiem//----------------------------------------------------------------------------- // name: readme-LiSa2.ck // desc: Live sampling utilities for ChucK // // author: Dan Trueman, 2007 // // LiSa allows for multiple voice playback from a live-sampled buffer. Useful // for granular sampling (a la [munger~] from PeRColate) and looping (a la // LoopLoop, Jamman, Echoplex, etc....). The methods are overloaded, taking // a "voice" number as a first arg. if no voice number is specified, LiSa // assumes 0=>voice. // // Below is a simple example to show how to crossfade two voices. See also the // LiSa-munger examples for other approaches. // // Below the example find a (lengthy) command summary. //----------------------------------------------------------------------------- // signal chain; record a sine wave, play it back SinOsc s => Envelope e => LiSa loopme => dac; s => dac; // direct monitor 440. => s.freq; 0.2 => s.gain; // alloc memory 6::second => loopme.duration; // play s for a bit 500::ms => now; // sweep the freq for fun Envelope pitchmod => blackhole; pitchmod.duration( 2000::ms ); pitchmod.value( s.freq() ); pitchmod.target( 880. ); // set times for recording fade in/out and sample loop length 100::ms => dur recfadetime; 1000::ms => dur mylooplen; e.duration( recfadetime ); // start recording input; record 1 seconds worth loopme.record( 1 ); // can also do without the Envelope and use loopme.recramp( dur ) to set a recording ramp e.keyOn(); now + (mylooplen - recfadetime) => time later; while( now < later ) { pitchmod.value() => s.freq; 10::ms => now; } e.keyOff(); recfadetime => now; loopme.record( 0 ); // disconnect input and hangout a bit s =< dac; 1000::ms => now; // now, manipulate the sample // get a voicenumber; note that this voice won't actually be reserved until you play it loopme.getVoice() => int voice1; // we'll play voice 1 forward, and then crossfade it with voice 2 backwards loopme.play( voice1, 1 ); (mylooplen - recfadetime) => now; // just as voice 1 is going to fade, bring in voice 2 loopme.getVoice() => int voice2; loopme.rate( voice2, -1. ); loopme.playPos( voice2, mylooplen ); loopme.play( voice2, 1 ); // wait until voice 1 had finished fading, then turn off recfadetime => now; loopme.play( voice1, 0 ); // wait for voice 2 to finish 1000::ms => now; //----------------------------------------------------------------------------- //LiSa Command Summary: // // mylisa.duration(dur); required -- sets max length of buffer // mylisa.record(1/0); turn on/off recording into buffer // mylisa.getVoice() => voice (int); returns first free voice number // mylisa.maxVoices(int); sets maximum # of allowable voices // mylisa.play(voice, 1/0); turn on/off play for particular voice // mylisa.rampUp(voice, dur); turn on play for voice with ramp // mylisa.rampDown(voice, dur); ramp down voice and then turn off play // mylisa.rate(voice, float); sets play rate for "voice" // mylisa.playPos(voice, dur); sets playback position for "voice" within buffer // mylisa.playPos(voice); returns playback position for "voice" // mylisa.recordPos(dur); sets record position // mylisa.recordPos(); gets record position // mylisa.recRamp(dur); sets ramping for the edges of the record buffer // mylisa.loopStart(dur, voice); sets loopstart point for "voice" // mylisa.loopStart(voice); get loopstart // mylisa.loopEnd(voice, dur); sets loopend point for "voice" // mylisa.loopEnd(voice); gets loopend // mylisa.loop(voice, 1/0); turn on/off looping for "voice" // mylisa.loop(voice); get looping state // mylisa.bi(voice, 1/0); turn on/off bidirectional looping for "voice" // mylisa.bi(voice); get bi state // mylisa.loopEndRec(dur); set looping end point for recording // mylisa.loopEndRec(); get ... // mylisa.feedback(float); set feedback amount [0,1] for recording // mylisa.feedback(); get... // mylisa.clear(); clear recording buffer // // All of these commands should work without the "voice" arg; 0=>voice will be assumed //----------------------------------------------------------------------------- chuck-1.2.0.8.dfsg/examples/status.ck0000644000175000017500000000032210600421722016014 0ustar piempiem// useful little shred for on-the-fly programming... // infinite time loop while( true ) { // print out machine status (same as chuck ^) Machine.status(); // every so often 3::second => now; } chuck-1.2.0.8.dfsg/examples/stereo/0000755000175000017500000000000010600421722015456 5ustar piempiemchuck-1.2.0.8.dfsg/examples/stereo/curly2.ck0000644000175000017500000000070210600421722017214 0ustar piempiem// impulse to filter to dac Impulse i => BiQuad f => Pan2 p => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // set filter resonant frequency Std.rand2f( 50, 5000 ) => f.pfreq; // pan Std.rand2f( -1, 1 ) => p.pan; // advance time 99::ms => now; } chuck-1.2.0.8.dfsg/examples/stereo/larry2.ck0000644000175000017500000000070410600421722017211 0ustar piempiem// impulse to filter to dac Impulse i => BiQuad f => Pan2 p => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // set filter resonant frequency Std.rand2f( 500, 5000 ) => f.pfreq; // pan Std.rand2f( -1, 1 ) => p.pan; // advance time 101::ms => now; } chuck-1.2.0.8.dfsg/examples/stereo/moe2.ck0000644000175000017500000000070310600421722016637 0ustar piempiem// impulse to filter to dac Impulse i => BiQuad f => Pan2 p => dac; // set the filter's pole radius .99 => f.prad; // set equal gain zeros 1 => f.eqzs; // set filter gain .5 => f.gain; // infinite time-loop while( true ) { // set the current sample/impulse 1.0 => i.next; // set filter resonant frequency Std.rand2f( 250, 5000 ) => f.pfreq; // pan Std.rand2f( -1, 1 ) => p.pan; // advance time 100::ms => now; } chuck-1.2.0.8.dfsg/examples/stereo/powerup2.ck0000644000175000017500000000216210600421722017561 0ustar piempiem// power up! // - philipd, stereo gewang 0.0 => float t; Noise n; // timer shred fun void timer() { while ( true ) { t + 0.01 => t; 10::ms => now; } } // spork the timer spork ~ timer(); // sweep shred fun void sweep( float st, float inc, float end, int c) { n => TwoPole z => Pan2 p => dac; 1 => z.norm; 0.1 => z.gain; t => float dt; st => float frq; Std.rand2f( -1, 1 ) => float s; Std.rand2f( -1, 1 ) => float e; ( e - s ) / ( end - t ) * .01 => float i; s => p.pan; Std.rand2f ( 0.94, 0.99 ) => z.radius; while ( t < end ) { Math.max( ( t - dt ) * 4.0, 1.0 ) * 0.1 => z.gain; frq + inc * -0.02 => frq; frq => z.freq; p.pan() + i => p.pan; 10::ms => now; } n =< z; z =< p; p =< dac; } 0 => int c; // time loop while ( true ) { 500::ms => dur d; if ( Std.rand2 ( 0, 10 ) > 3 ) d * 2.0 => d; if ( Std.rand2 ( 0, 10 ) > 6 ) d * 3.0 => d; spork ~ sweep( 220.0 * Std.rand2(1,8), 880.0 + Std.rand2f(100.0, 880.0), t + Std.rand2f(1.0, 3.0) , c); 1 + c => c; d => now; } chuck-1.2.0.8.dfsg/examples/stereo/stereo_noise.ck0000644000175000017500000000071210600421722020473 0ustar piempiem// the patch, note pan2 is stereo Noise n => Pan2 p => dac; .1 => n.gain; // variable 0.0 => float t; // smaller == smoother 10::ms => dur T; // time loop while( true ) { // pan goes from -1 (left) to 1 (right) Math.sin(t) => p.pan; // increment t (scaling by T) T / second * 2.5 +=> t; // uncomment to print out pan, last left, last right // <<>>; // advancde time T => now; } chuck-1.2.0.8.dfsg/examples/stk/0000755000175000017500000000000010600421722014756 5ustar piempiemchuck-1.2.0.8.dfsg/examples/stk/band-o-matic.ck0000644000175000017500000000254010600421722017531 0ustar piempiem// banded waveguide sample // the patch BandedWG band => JCRev r => dac; // presets 0.95 => band.gain; 1 => band.preset; Std.mtof( ( 21 + Std.rand2(0,3) * 12 + 7 ) ) => band.freq; .8 => r.gain; .1 => r.mix; // scale [ 0, 2, 4, 7, 9 ] @=> int scale[]; // our main time loop while( true ) { Std.rand2f( 0.1, 0.9 ) => band.bowRate; Std.rand2f( 0.2, 0.35 ) => band.bowPressure; Std.rand2f( 0.6, 0.8 ) => band.startBowing; if( Std.randf() > 0.7 ) { 1000::ms => now; } else if( Std.randf() > .7 ) { 500::ms => now; } else if( Std.randf() > 0.2 ) { .250::second => now; } else { 0 => int i; 4 * Std.rand2( 1, 4 ) => int pick; 0 => int pick_dir; 0.0 => float pluck; Std.rand2f( 50.0, 200.0 ) => float d; for( ; i < pick; 1 +=> i ) { Std.rand2f(.4,.6) + i*.35/pick => pluck; pluck + 0.1 * pick_dir => band.pluck; !pick_dir => pick_dir; d::ms => now; } } if ( Std.randf() > 0.2 ) { 1::second => now; 0.001 => band.stopBowing; 0.5::second * Std.rand2(1,3) => now; // scale scale[Std.rand2(0, scale.cap()-1)] => int freq; Std.mtof( 21 + Std.rand2(0,5) * 12 + freq ) => band.freq; if ( Std.randf() > 0.7 ) Std.rand2(0,3) => band.preset; } } chuck-1.2.0.8.dfsg/examples/stk/bandedwg.ck0000644000175000017500000000174510600421722017057 0ustar piempiem// STK BandedWG // patch BandedWG bwg => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2f( 0, 1 ) => bwg.bowRate; Std.rand2f( 0, 1 ) => bwg.bowPressure; Std.rand2f( 0, 1 ) => bwg.strikePosition; Std.rand2(0, 3) => bwg.preset; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => bwg.freq; // print some parameters <<< "---", "" >>>; <<< "preset:", bwg.preset() >>>; <<< "bow rate:", bwg.bowRate() >>>; <<< "bow Pressure:", bwg.bowPressure() >>>; <<< "strike position:", bwg.strikePosition() >>>; <<< "frequency:", bwg.freq() >>>; <<< "---", "" >>>; <<< "bow -> pluck", "" >>>; Std.rand2f( .5, 1 ) => bwg.pluck; // advance time 2::second => now; <<< "pluck -> bow", "" >>>; .8 => bwg.startBowing; Std.rand2f(2,4)::second => now; 1.0 => bwg.stopBowing; 1::second => now; } chuck-1.2.0.8.dfsg/examples/stk/bandedwg2.ck0000644000175000017500000000364510600421722017142 0ustar piempiem// STK BandedWG // patch BandedWG bwg => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2f( 0, 1 ) => bwg.pluck; Std.rand2f( 0, 128 ) => float bowPressure; Std.rand2f( 0, 128 ) => float bowMotion; Std.rand2f( 0, 128 ) => float strikePosition; Std.rand2f( 0, 128 ) => float vibratoFreq; Std.rand2f( 0, 128 ) => float gain; Std.rand2f( 0, 128 ) => float bowVelocity; Std.rand2f( 0, 128 ) => float setStriking; Std.rand2f( 0, 3 ) => float preset; Std.rand2f( 0, 1) => bwg.bowRate; bwg.controlChange( 2, bowPressure); bwg.controlChange( 4, bowMotion); bwg.controlChange( 8, strikePosition); bwg.controlChange( 11, vibratoFreq); bwg.controlChange( 1, gain); bwg.controlChange( 128, bowVelocity); bwg.controlChange( 64, setStriking); <<< "---", "" >>>; <<< "strike position:", bwg.strikePosition() >>>; <<< "bow rate:", bwg.bowRate() >>>; <<< "bow Pressure:", bwg.bowPressure() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => bwg.freq; // go .8 => bwg.noteOn; // advance time 1::second => now; 1.0 => bwg.noteOff; .5::second => now; <<< "pluck -> bow", "" >>>; .8 => bwg.startBowing; 1::second => now; 1.0 => bwg.stopBowing; <<< "--", "" >>>; bwg.controlChange(16, Std.rand2(0, 3)); <<< "preset:", bwg.preset() >>>; <<< "strike position:", bwg.strikePosition() >>>; <<< "bow rate:", bwg.bowRate() >>>; <<< "bow Pressure:", bwg.bowPressure() >>>; // set freq 57 + Std.rand2(0,2)*12 + winner => Std.mtof => bwg.freq; // go .8 => bwg.noteOn; // advance time 1::second => now; 1.0 => bwg.noteOff; .5::second => now; <<< "pluck -> bow", "" >>>; .8 => bwg.startBowing; 1::second => now; 1.0 => bwg.stopBowing; } chuck-1.2.0.8.dfsg/examples/stk/blowbotl.ck0000644000175000017500000000132110600421722017116 0ustar piempiem// STK BlowBotl // patch BlowBotl bottle => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2f( 0, 1 ) => bottle.noiseGain; Std.rand2f( 0, 12 ) => bottle.vibratoFreq; Std.rand2f( 0, 1 ) => bottle.vibratoGain; Std.rand2f( 0, 1 ) => bottle.volume; // print <<< "---", "" >>>; <<< "noise gain:", bottle.noiseGain() >>>; <<< "vibrato freq:", bottle.vibratoFreq() >>>; <<< "vibrato gain:", bottle.vibratoGain() >>>; <<< "volume:", bottle.volume() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] + 57 => Std.mtof => bottle.freq; // go .8 => bottle.noteOn; // advance time 1::second => now; } chuck-1.2.0.8.dfsg/examples/stk/blowbotl2.ck0000644000175000017500000000176210600421722017211 0ustar piempiem// STK BlowBotl; using classic STK controlChange // (also see blowbotl.ck) // patch BlowBotl bottle => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { Std.rand2f( 0, 128 ) => float noisegain; Std.rand2f( 0, 128 ) => float vibratofreq; Std.rand2f( 0, 128 ) => float vibratogain; Std.rand2f( 0, 128 ) => float volume; <<< "---", "" >>>; <<< "noise gain:", noisegain, "/ 128.0" >>>; <<< "vibrato freq:", vibratofreq, "/ 128.0" >>>; <<< "vibrato gain:", vibratogain, "/ 128.0" >>>; <<< "volume:", volume, "/ 128.0" >>>; // noise gain bottle.controlChange( 4, noisegain ); // vibrato freq bottle.controlChange( 11, vibratofreq ); // vibrato gain bottle.controlChange( 1, vibratogain ); // volume bottle.controlChange( 128, volume ); // set freq scale[Std.rand2(0,scale.cap()-1)] + 57 => Std.mtof => bottle.freq; // go .8 => bottle.noteOn; // advance time 1::second => now; } chuck-1.2.0.8.dfsg/examples/stk/blowhole.ck0000644000175000017500000000211110600421722017103 0ustar piempiem// patch BlowHole hole => dac; // scale [0, 2, 4, 7, 9, 11] @=> int scale[]; <<< "reed stiffness:", hole.reed() >>>; <<< "noise gain:", hole.noiseGain() >>>; <<< "tonehole state:", hole.tonehole() >>>; <<< "register state:", hole.vent() >>>; <<< "breath pressure:", hole.pressure() >>>; // infinite time loop while( true ) { // change parameters if( Std.rand2f(0,1) > .75 ) { Std.rand2f( 0, 1 ) => hole.reed; Std.rand2f( 0, 1 ) => hole.noiseGain; Std.rand2f( 0, 1 ) => hole.tonehole; Std.rand2f( 0, 1 ) => hole.vent; Std.rand2f( 0, 1 ) => hole.pressure; // print <<< "going...", "" >>>; <<< "reed stiffness:", hole.reed() >>>; <<< "noise gain:", hole.noiseGain() >>>; <<< "tonehole state:", hole.tonehole() >>>; <<< "register state:", hole.vent() >>>; <<< "breath pressure:", hole.pressure() >>>; } // set freq scale[Std.rand2(0,scale.cap()-1)] => int note; 33 + Std.rand2(0,4)*12 + note => Std.mtof => hole.freq; <<< "note: ", Std.ftom( hole.freq() ) >>>; // go .8 => hole.noteOn; // advance time 1::second => now; } chuck-1.2.0.8.dfsg/examples/stk/blowhole2.ck0000644000175000017500000000232010600421722017167 0ustar piempiem// patch BlowHole hole => dac; // scale [0, 2, 4, 7, 9, 11] @=> int scale[]; // infinite time loop while( true ) { // change parameters if( Std.rand2f(0,1) > .75 ) { Std.rand2f( 0, 128 ) => float stiffness; Std.rand2f( 0, 128 ) => float noisegain; Std.rand2f( 0, 128 ) => float tonehole; Std.rand2f( 0, 128 ) => float register; Std.rand2f( 0, 128 ) => float pressure; <<< "going...", "" >>>; <<< "reed stiffness:", stiffness, "/ 128.0" >>>; <<< "noise gain:", noisegain, "/ 128.0" >>>; <<< "tonehole state:", tonehole, "/ 128.0" >>>; <<< "register state:", register, "/ 128.0" >>>; <<< "breath pressue:", pressure, "/ 128.0" >>>; // reed stiffness hole.controlChange( 2, stiffness ); // noise gain hole.controlChange( 4, noisegain ); // tonehole state hole.controlChange( 11, tonehole ); // register state hole.controlChange( 1, register ); // breath pressue hole.controlChange( 128, pressure ); } // set freq scale[Std.rand2(0,scale.cap()-1)] => int note; 33 + Std.rand2(0,4)*12 + note => Std.mtof => hole.freq; <<< "note: ", Std.ftom( hole.freq() ) >>>; // go .8 => hole.noteOn; // advance time 1::second => now; } chuck-1.2.0.8.dfsg/examples/stk/bowed.ck0000644000175000017500000000141310600421722016374 0ustar piempiem// patch Bowed bow => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // set Std.rand2f( 0, 1 ) => bow.bowPressure; Std.rand2f( 0, 1 ) => bow.bowPosition; Std.rand2f( 0, 12 ) => bow.vibratoFreq; Std.rand2f( 0, 1 ) => bow.vibratoGain; Std.rand2f( 0, 1 ) => bow.volume; // print <<< "---", "" >>>; <<< "bow pressure:", bow.bowPressure() >>>; <<< "bow position:", bow.bowPosition() >>>; <<< "vibrato freq:", bow.vibratoFreq() >>>; <<< "vibrato gain:", bow.vibratoGain() >>>; <<< "volume:", bow.volume() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] + 57 => Std.mtof => bow.freq; // go .8 => bow.noteOn; // advance time Std.rand2f(.8, 2)::second => now; } chuck-1.2.0.8.dfsg/examples/stk/bowed2.ck0000644000175000017500000000200010600421722016447 0ustar piempiem// patch Bowed bow => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { Std.rand2f( 0, 128 ) => float pressure; Std.rand2f( 0, 128 ) => float position; Std.rand2f( 0, 128 ) => float vibratofreq; Std.rand2f( 0, 128 ) => float vibratogain; Std.rand2f( 0, 128 ) => float volume; <<< "---", "" >>>; <<< "bow pressure:", pressure >>>; <<< "bow position:", position >>>; <<< "vibrato freq:", vibratofreq >>>; <<< "vibrato gain:", vibratogain >>>; <<< "volume:", volume >>>; // bow pressure bow.controlChange( 2, pressure ); // bow position bow.controlChange( 4, position ); // vibrato freq bow.controlChange( 11, vibratofreq ); // vibrato gain bow.controlChange( 1, vibratogain ); // volume bow.controlChange( 128, volume ); // set freq scale[Std.rand2(0,scale.cap()-1)] + 57 => Std.mtof => bow.freq; // go .8 => bow.noteOn; // advance time Std.rand2f(.8, 2)::second => now; } chuck-1.2.0.8.dfsg/examples/stk/brass.ck0000644000175000017500000000170210600421722016407 0ustar piempiem// patch Brass brass => JCRev r => dac; .75 => r.gain; .1 => r.mix; // our notes [ 61, 63, 65, 66, 68 ] @=> int notes[]; // infinite time-loop while( true ) { // set Std.rand2f( 0, 1 ) => brass.lip; Std.rand2f( 0, 1 ) => brass.slide; Std.rand2f( 0, 12 ) => brass.vibratoFreq; Std.rand2f( 0, 1 ) => brass.vibratoGain; Std.rand2f( 0, 1 ) => brass.volume; // print <<< "---", "" >>>; <<< "lip tension:", brass.lip() >>>; <<< "slide length:", brass.slide() >>>; <<< "vibrato freq:", brass.vibratoFreq() >>>; <<< "vibrato gain:", brass.vibratoGain() >>>; <<< "volume:", brass.volume() >>>; for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => brass.freq; velocity => brass.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/brass2.ck0000644000175000017500000000230110600421722016465 0ustar piempiem// patch Brass brass => JCRev r => dac; .75 => r.gain; .1 => r.mix; // our notes [ 61, 63, 65, 66, 68 ] @=> int notes[]; // infinite time-loop while( true ) { Std.rand2f( 64, 128 ) => float tension; Std.rand2f( 0, 128 ) => float length; Std.rand2f( 0, 128 ) => float vibratofreq; Std.rand2f( 0, 128 ) => float vibratogain; Std.rand2f( 64, 128 ) => float volume; <<< "---", "" >>>; <<< "lip tension:", tension >>>; <<< "slide length:", length >>>; <<< "vibrato freq:", vibratofreq >>>; <<< "vibrato gain:", vibratogain >>>; <<< "volume:", volume >>>; // lip tension brass.controlChange( 2, tension ); // slide length brass.controlChange( 4, length ); // vibrato freq brass.controlChange( 11, vibratofreq ); // vibrato gain brass.controlChange( 1, vibratogain ); // volume brass.controlChange( 128, volume ); for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => brass.freq; velocity => brass.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/clarinet.ck0000644000175000017500000000211610600421722017076 0ustar piempiem// STK Clarinet // (also see examples/event/polyfony2.ck) // patch Clarinet clair => JCRev r => dac; .75 => r.gain; .1 => r.mix; // our notes [ 61, 63, 65, 66, 68, 66, 65, 63, 61 ] @=> int notes[]; // infinite time-loop while( true ) { // clear clair.clear( 1.0 ); // set Std.rand2f( 0, 1 ) => clair.reed; Std.rand2f( 0, 1 ) => clair.noiseGain; Std.rand2f( 0, 12 ) => clair.vibratoFreq; Std.rand2f( 0, 1 ) => clair.vibratoGain; Std.rand2f( 0, 1 ) => clair.pressure; // print <<< "---", "" >>>; <<< "reed stiffness:", clair.reed() >>>; <<< "noise gain:", clair.noiseGain() >>>; <<< "vibrato freq:", clair.vibratoFreq() >>>; <<< "vibrato gain:", clair.vibratoGain() >>>; <<< "breath pressure:", clair.pressure() >>>; for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => clair.freq; velocity => clair.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/clarinet2.ck0000644000175000017500000000253610600421722017166 0ustar piempiem// STK Clarinet // (also see examples/event/polyfony2.ck) // patch Clarinet clair => JCRev r => dac; .75 => r.gain; .1 => r.mix; // our notes [ 61, 63, 65, 66, 68, 66, 65, 63, 61 ] @=> int notes[]; // infinite time-loop while( true ) { Std.rand2f( 64, 128 ) => float stiffness; Std.rand2f( 0, 128 ) => float noisegain; Std.rand2f( 0, 128 ) => float vibratofreq; Std.rand2f( 0, 128 ) => float vibratogain; Std.rand2f( 64, 128 ) => float pressure; <<< "---", "" >>>; <<< "reed stiffness:", stiffness >>>; <<< "noise gain:", noisegain >>>; <<< "vibrato freq:", vibratofreq >>>; <<< "vibrato gain:", vibratogain >>>; <<< "breath pressure:", pressure >>>; // clear clair.clear( 1.0 ); // reed stiffness clair.controlChange( 2, stiffness ); // noise gain clair.controlChange( 4, noisegain ); // vibrato freq clair.controlChange( 11, vibratofreq ); // vibrato gain clair.controlChange( 1, vibratogain ); // breath pressure clair.controlChange( 128, pressure ); for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => clair.freq; velocity => clair.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/flute.ck0000644000175000017500000000247010600421722016417 0ustar piempiem// STK Flute // patch Flute flute => PoleZero f => JCRev r => dac; .75 => r.gain; .05 => r.mix; 1 => f.blockZero; // our notes [ 61, 63, 65, 66, 68 ] @=> int notes[]; // infinite time-loop while( true ) { // clear flute.clear( 1.0 ); // set Std.rand2f( 0, 1 ) => flute.jetDelay; Std.rand2f( 0, 1 ) => flute.jetReflection; Std.rand2f( 0, 1 ) => flute.endReflection; Std.rand2f( 0, 1 ) => flute.noiseGain; Std.rand2f( 0, 12 ) => flute.vibratoFreq; Std.rand2f( 0, 1 ) => flute.vibratoGain; Std.rand2f( 0, 1 ) => flute.pressure; // print <<< "---", "" >>>; <<< "jetDelay:", flute.jetDelay() >>>; <<< "jetReflection:", flute.jetReflection() >>>; <<< "endReflection:", flute.endReflection() >>>; <<< "noiseGain:", flute.noiseGain() >>>; <<< "vibratoFreq:", flute.vibratoFreq() >>>; <<< "vibratoGain:", flute.vibratoGain() >>>; <<< "breath pressure:", flute.pressure() >>>; // factor Std.rand2f( .75, 2 ) => float factor; for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms * factor => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => flute.freq; velocity => flute.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/mand-o-matic.ck0000644000175000017500000000442410600421722017547 0ustar piempiem//---------------| // mand-o-matic! // by: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //------------------| // our patch Mandolin mand => JCRev r => Echo a => Echo b => Echo c => dac; // set the gain .95 => r.gain; // set the reverb mix .2 => r.mix; // set max delay for echo 1000::ms => a.max => b.max => c.max; // set delay for echo 750::ms => a.delay => b.delay => c.delay; // set the initial effect mix 0.0 => a.mix => b.mix => c.mix; // scale [ 0, 2, 4, 7, 9 ] @=> int scale[]; // shred to modulate the mix fun void echo_Shred( ) { 0.0 => float decider => float mix => float old => float inc; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .35 ) 0.0 => mix; else if( decider < .55 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => int n; // time loop while( n-- ) { // set the mix for a, b, c old + inc => old => a.mix => b.mix => c.mix; 1::ms => now; } // remember the old mix => old; // let time pass until the next iteration Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ echo_Shred(); // our main loop while( true ) { // position Std.rand2f( 0.2, 0.8 ) => mand.pluckPos; // frequency... scale[Std.rand2(0,scale.cap()-1)] => int freq; 220.0 * Math.pow( 1.05946, (Std.rand2(0,2)*12) + freq ) => mand.freq; // pluck it! Std.rand2f( 0.2, 0.9 ) => mand.pluck; if( Std.randf() > 0.8 ) { 500::ms => now; } else if( Std.randf() > .85 ) { 250::ms => now; } else if( Std.randf() > -0.9 ) { .125::second => now; } else { 1 => int i => int pick_dir; // how many times 4 * Std.rand2( 1, 5 ) => int pick; 0.0 => float pluck; 0.7 / pick => float inc; // time loop for( ; i < pick; i++ ) { 75::ms => now; Std.rand2f(.2,.3) + i*inc => pluck; pluck + -.2 * pick_dir => mand.pluck; // simulate pluck direction !pick_dir => pick_dir; } // let time pass for final pluck 75::ms => now; } } chuck-1.2.0.8.dfsg/examples/stk/mandolin.ck0000644000175000017500000000172410600421722017102 0ustar piempiem// STK Mandolin // patch Mandolin m => JCRev r => dac; .75 => r.gain; .05 => r.mix; // our notes [ 61, 63, 65, 66, 68, 66, 65, 63 ] @=> int notes[]; // infinite time-loop while( true ) { // set Std.rand2f( 0, 1 ) => m.bodySize; Std.rand2f( 0, 1 ) => m.pluckPos; // Std.rand2f( 0, 1 ) => m.stringDamping; // Std.rand2f( 0, 1 ) => m.stringDetune; // print <<< "---", "" >>>; <<< "body size:", m.bodySize() >>>; <<< "pluck position:", m.pluckPos() >>>; <<< "string damping:", m.stringDamping() >>>; <<< "string detune:", m.stringDetune() >>>; // factor Std.rand2f( 1, 4 ) => float factor; for( int i; i < notes.cap(); i++ ) { play( Std.rand2(0,2)*12 + notes[i], Std.rand2f( .6, .9 ) ); 100::ms * factor => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => m.freq; velocity => m.pluck; } chuck-1.2.0.8.dfsg/examples/stk/modalbar.ck0000644000175000017500000000211010600421722017050 0ustar piempiem// STK ModalBar // patch ModalBar bar => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2( 0, 8 ) => bar.preset; Std.rand2f( 0, 1 ) => bar.stickHardness; Std.rand2f( 0, 1 ) => bar.strikePosition; Std.rand2f( 0, 1 ) => bar.vibratoGain; Std.rand2f( 0, 60 ) => bar.vibratoFreq; Std.rand2f( 0, 1 ) => bar.volume; Std.rand2f( .5, 1 ) => bar.directGain; Std.rand2f( .5, 1 ) => bar.masterGain; // print <<< "---", "" >>>; <<< "preset:", bar.preset() >>>; <<< "stick hardness:", bar.stickHardness() >>>; <<< "strike position:", bar.strikePosition() >>>; <<< "vibrato gain:", bar.vibratoGain() >>>; <<< "vibrato freq:", bar.vibratoFreq() >>>; <<< "volume:", bar.volume() >>>; <<< "direct gain:", bar.directGain() >>>; <<< "master gain:", bar.masterGain() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => bar.freq; // go .8 => bar.noteOn; // advance time .5::second => now; } chuck-1.2.0.8.dfsg/examples/stk/modalbar2.ck0000644000175000017500000000262010600421722017140 0ustar piempiem// STK ModalBar // patch ModalBar bar => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2( 0, 8 ) => int preset; Std.rand2f( 0, 128 ) => float stickHardness; Std.rand2f( 0, 128 ) => float strikePosition; Std.rand2f( 0, 128 ) => float vibratoGain; Std.rand2f( 0, 128 ) => float vibratoFreq; Std.rand2f( 0, 128 ) => float volume; Std.rand2f( 64, 128 ) => float directGain; Std.rand2f( 64, 128 ) => float masterGain; bar.controlChange( 2, stickHardness ); bar.controlChange( 4, strikePosition ); bar.controlChange( 11, vibratoGain ); bar.controlChange( 7, vibratoFreq ); bar.controlChange( 1, directGain); bar.controlChange( 128, volume ); bar.controlChange( 16, preset ); <<< "---", "" >>>; <<< "preset:", preset >>>; <<< "stick hardness:", stickHardness, "/ 128.0" >>>; <<< "strike position:", strikePosition, "/ 128.0" >>>; <<< "vibrato gain:", vibratoGain, "/ 128.0" >>>; <<< "vibrato freq:", vibratoFreq, "/ 128.0" >>>; <<< "volume:", volume, "/ 128.0" >>>; <<< "direct gain:", directGain, "/ 128.0" >>>; <<< "master gain:", masterGain, "/ 128.0" >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => bar.freq; // go .8 => bar.noteOn; // advance time .5::second => now; } chuck-1.2.0.8.dfsg/examples/stk/mode-o-matic.ck0000644000175000017500000000472710600421722017562 0ustar piempiem//---------------| // modal demo // based off of mand-o-matic ( master plan ) // by : philipd // by: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //------------------| // our patch ModalBar modey => JCRev r => Echo a => Echo b => Echo c => dac; // set the gain .95 => r.gain; // set the reverb mix .2 => r.mix; // set max delay for echo 1000::ms => a.max => b.max => c.max; // set delay for echo 750::ms => a.delay => b.delay => c.delay; // set the initial effect mix 0.0 => a.mix => b.mix => c.mix; // shred to modulate the mix fun void echo_Shred( ) { 0.0 => float decider => float mix => float old => float inc; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .35 ) 0.0 => mix; else if( decider < .55 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => int n; // time loop while( n-- ) { // set the mix for a, b, c old + inc => old => a.mix => b.mix => c.mix; 1::ms => now; } // remember the old mix => old; // let time pass until the next iteration Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ echo_Shred(); // scale [ 0, 2, 4, 7, 9, 11 ] @=> int scale[]; // our main loop while( true ) { //presets if ( Std.randf() > 0.9 ) Std.rand2 (0,8) => modey.preset; // position Std.rand2f( 0.2, 0.8 ) => modey.strikePosition; // frequency... scale[Std.rand2(0,scale.cap()-1)] => int freq; Std.mtof( 45 + Std.rand2(0,4)*12 + freq ) => modey.freq; // pluck it! Std.rand2f( 0.2, 0.6 ) => modey.strike; if( Std.randf() > 0.8 ) { 500::ms => now; } else if( Std.randf() > .85 ) { 250::ms => now; } else if( Std.randf() > -0.9 ) { .125::second => now; } else { 1 => int i => int pick_dir; // how many times 4 * Std.rand2( 1, 5 ) => int pick; 0.0 => float pluck; 0.65 / pick => float inc; // time loop for( ; i < pick; i++ ) { 75::ms => now; Std.rand2f(.2,.3) + i*inc => pluck; pluck => modey.stickHardness; pluck + -.2 * pick_dir => modey.strike; // simulate pluck direction !pick_dir => pick_dir; } // let time pass for final pluck 75::ms => now; } } chuck-1.2.0.8.dfsg/examples/stk/mode-o-test.ck0000644000175000017500000000172310600421722017435 0ustar piempiem//---------------| // modal demo // by: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //------------------| // our patch ModalBar modey => JCRev r => dac; // set the gain .95 => r.gain; // set the reverb mix .1 => r.mix; // scale [ 0, 2, 4, 7, 9, 11 ] @=> int scale[]; int which; // our main loop while( true ) { // cycle through ( which + 1 ) % 9 => which; which => modey.preset; // frequency... scale[Std.rand2(0,scale.cap()-1)] => int freq; Math.mtof( 33 + (Std.rand2(0,3)*12) + freq ) => modey.freq; // velocity Std.rand2f( 0.4, 0.8 ) => float v; <<< "playing:", which, "freq:", Std.ftom(modey.freq()) $ int, "vel:", v >>>; repeat( 4 ) { // position Std.rand2f( 0.2, 0.8 ) => float p => modey.strikePosition; // strike it! v => modey.strike; // print <<< " strike position:", p >>>; // advance time 250::ms => now; } } chuck-1.2.0.8.dfsg/examples/stk/modulate.ck0000644000175000017500000000045410600421722017112 0ustar piempiem// patch into gain SinOsc s => Gain g => dac; Modulate mod => g; // multiply 3 => g.op; // set freq 220 => s.freq; // set rate in hz mod.vibratoRate( 6.0 ); // set gain mod.vibratoGain( .2 ); // set random gain mod.randomGain( .1 ); // infinite time loop while( true ) { 10::second => now; } chuck-1.2.0.8.dfsg/examples/stk/moog.ck0000644000175000017500000000146710600421722016246 0ustar piempiem// STK ModalBar // patch Moog moog => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2f( 0, 1 ) => moog.filterQ; Std.rand2f( 0, 1 ) => moog.filterSweepRate; Std.rand2f( 0, 12 ) => moog.lfoSpeed; Std.rand2f( 0, 1 ) => moog.lfoDepth; Std.rand2f( 0, 1 ) => moog.volume; // print <<< "---", "" >>>; <<< "filterQ", moog.filterQ() >>>; <<< "filter sweep rate:", moog.filterSweepRate() >>>; <<< "lfo speed:", moog.lfoSpeed() >>>; <<< "lfo depth:", moog.lfoDepth() >>>; <<< "volume:", moog.volume() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => moog.freq; // go .8 => moog.noteOn; // advance time .5::second => now; } chuck-1.2.0.8.dfsg/examples/stk/moog2.ck0000644000175000017500000000213510600421722016321 0ustar piempiem// STK ModalBar // patch Moog moog => dac; // scale [0, 2, 4, 7, 8, 11] @=> int scale[]; // infinite time loop while( true ) { // ding! Std.rand2f( 0, 128 ) => float filterQ; Std.rand2f( 0, 128 ) => float filterSweep; Std.rand2f( 0, 128 ) => float vol; Std.rand2f( 0, 128 ) => float vibratoFreq; Std.rand2f( 0, 128 ) => float vibratoGain; moog.controlChange( 2, filterQ); moog.controlChange( 4, filterSweep); moog.controlChange( 11, vibratoFreq); moog.controlChange( 1, vibratoGain); moog.controlChange( 128, vol); <<< "---", "" >>>; <<< "filterQ", moog.filterQ() >>>; <<< "filter sweep rate:", moog.filterSweepRate() >>>; <<< "mod speed:", moog.lfoSpeed() >>>; <<< "mod depth:", moog.lfoDepth() >>>; <<< "volume:", moog.volume() >>>; <<< "vibrato freq:", moog.vibratoFreq() >>>; <<< "vibrato gain:", moog.vibratoGain() >>>; // set freq scale[Std.rand2(0,scale.cap()-1)] => int winner; 57 + Std.rand2(0,2)*12 + winner => Std.mtof => moog.freq; // go .8 => moog.noteOn; // advance time .5::second => now; } chuck-1.2.0.8.dfsg/examples/stk/moogie.ck0000644000175000017500000000164010600421722016555 0ustar piempiem// STK Moog // by: phil Moog mog => dac; 440.0 => mog.freq; 0.0 => float t; fun void varmod() { while ( true ) { 0.5 + 0.4 * Math.sin ( t * 0.1 ) => mog.modDepth; 0.5 + 0.4 * Math.sin ( t * 0.2 ) => mog.modSpeed; 0.5 + 0.4 * Math.sin ( t * 0.3 ) => mog.filterQ; 0.5 + 0.4 * Math.sin ( t * 0.4 ) => mog.filterSweepRate; 10::ms => now; t + 0.01 => t; } } fun void atouch( float imp) { imp => float atouch; while ( atouch >= 0.0 ) { atouch => mog.afterTouch; atouch - 0.05 => atouch; 10::ms => now; } } // spork varmod shred spork ~varmod(); 0.0 => float vel; while ( true ) { // Std.rand2f ( 440.0, 880.0 ) => mog.freq; 278.43 => mog.freq; Std.rand2f(0.5, 0.8) => vel; vel => mog.noteOn; spork ~ atouch(vel); if ( Std.randf() > 0.3 ) { 1::second => now; } else { 0.5::second => now; } } chuck-1.2.0.8.dfsg/examples/stk/rhodey.ck0000644000175000017500000000340110600421722016565 0ustar piempiem// more music for replicants // patch Rhodey voc=> JCRev r => Echo a => Echo b => Echo c => dac; 220.0 => voc.freq; 0.8 => voc.gain; .8 => r.gain; .2 => r.mix; 1000::ms => a.max => b.max => c.max; 750::ms => a.delay => b.delay => c.delay; .50 => a.mix => b.mix => c.mix; // shred to modulate the mix fun void vecho_Shred( ) { 0.0 => float decider; 0.0 => float mix; 0.0 => float old; 0.0 => float inc; 0 => int n; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .3 ) 0.0 => mix; else if( decider < .6 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => n; while( n-- ) { old + inc => old; old => a.mix => b.mix => c.mix; 1::ms => now; } mix => old; Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ vecho_Shred(); // scale [ 0, 2, 4, 7, 9 ] @=> int scale[]; // our main loop while( true ) { // pentatonic scale[Std.rand2(0,scale.cap()-1)] => int freq; Std.mtof( ( 33 + Std.rand2(0,1) * 12 + freq ) ) => voc.freq; Std.rand2f( 0.6, 0.8 ) => voc.noteOn; if( Std.randf() > 0.7 ) { 1000::ms => now; } else if( Std.randf() > .7 ) { 500::ms => now; } else if( Std.randf() > -0.8 ) { .250::second => now; } else { 0 => int i; 2 * Std.rand2( 1, 3 ) => int pick; 0 => int pick_dir; 0.0 => float pluck; for( ; i < pick; i++ ) { Std.rand2f(.4,.6) + i*.035 => pluck; pluck + -0.02 * (i * pick_dir) => voc.noteOn; !pick_dir => pick_dir; 250::ms => now; } } } chuck-1.2.0.8.dfsg/examples/stk/saxofony.ck0000644000175000017500000000227710600421722017153 0ustar piempiem// STK Saxofony // patch Saxofony sax => JCRev r => dac; .5 => r.gain; .05 => r.mix; // our notes [ 61, 63, 65, 66, 68 ] @=> int notes[]; // infinite time-loop while( true ) { // set Std.rand2f( 0, 1 ) => sax.stiffness; Std.rand2f( 0, 1 ) => sax.aperture; Std.rand2f( 0, 1 ) => sax.noiseGain; Std.rand2f( 0, 1 ) => sax.blowPosition; Std.rand2f( 0, 12 ) => sax.vibratoFreq; Std.rand2f( 0, 1 ) => sax.vibratoGain; Std.rand2f( 0, 1 ) => sax.pressure; // print <<< "---", "" >>>; <<< "stiffness:", sax.stiffness() >>>; <<< "aperture:", sax.aperture() >>>; <<< "noiseGain:", sax.noiseGain() >>>; <<< "blowPosition:", sax.blowPosition() >>>; <<< "vibratoFreq:", sax.vibratoFreq() >>>; <<< "vibratoGain:", sax.vibratoGain() >>>; <<< "pressure:", sax.pressure() >>>; // factor Std.rand2f( .75, 2 ) => float factor; for( int i; i < notes.cap(); i++ ) { play( 12 + notes[i], Std.rand2f( .6, .9 ) ); 300::ms * factor => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => sax.freq; velocity => sax.noteOn; } chuck-1.2.0.8.dfsg/examples/stk/shake-cycle.ck0000644000175000017500000000057410600421722017473 0ustar piempiem// shake-cycle.ck : effects abuse // author: Adam Tindale // the patch Shakers s => Chorus c1 => JCRev rev => Chorus c2 => Chorus c3 =>dac; 0 => s.which; 1 => s.gain; 100 => float theTime; while( true ) { 1.0 => s.noteOn; theTime::ms => now; 1.0 => s.noteOff; theTime::ms => now; ( s.which() + 1 ) % 20 => s.which; Std.rand2f(20,140) => theTime; } chuck-1.2.0.8.dfsg/examples/stk/shake-o-matic.ck0000644000175000017500000000236610600421722017726 0ustar piempiem//---------------| // shake-o-matic! // by: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //------------------| // our patch Shakers shake => JCRev r => dac; // set the gain //.95 => r.gain; // set the reverb mix //.2 => r.mix; // our main loop while( true ) { // frequency.. if ( Std.randf() > 0.25 ) { Std.rand2( 0, 22 ) => shake.which; Std.mtof( Std.rand2f( 0.0, 128.0 ) ) => shake.freq; <<< "instrument #:", shake.which() >>>; } // shake it! Std.rand2f( 0.8, 1.3 ) => shake.noteOn; if( Std.randf() > 0.8 ) { 500::ms => now; } else if( Std.randf() > .85 ) { 250::ms => now; } else if( Std.randf() > -0.9 ) { .125::second => now; } else { 1 => int i => int pick_dir; // how many times 4 * Std.rand2( 1, 5 ) => int pick; 0.0 => float pluck; 0.7 / pick => float inc; // time loop for( ; i < pick; i++ ) { 75::ms => now; Std.rand2f(.2,.3) + i*inc => pluck; pluck + -.2 * pick_dir => shake.noteOn; // simulate pluck direction !pick_dir => pick_dir; } // let time pass for final shake 75::ms => now; } } chuck-1.2.0.8.dfsg/examples/stk/sitar.ck0000644000175000017500000000060110600421722016414 0ustar piempiem// patch Sitar sit => PRCRev r => dac; .15 => r.mix; // time loop while( true ) { // freq Std.rand2( 0, 11 ) => float winner; Std.mtof( 57 + Std.rand2(0,3) * 12 + winner ) => sit.freq; // pluck! Std.rand2f( 0.4, 0.9 ) => sit.noteOn; // advance time if ( Std.randf() > 0.0 ) { .5::second => now; } else { 0.25::second => now; } } chuck-1.2.0.8.dfsg/examples/stk/stif-o-karp.ck0000644000175000017500000000455710600421722017444 0ustar piempiem//---------------| // karp-o-matic! // by: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //------------------| // our patch StifKarp karp => JCRev r => Echo a => Echo b => Echo c => dac; // set the gain .95 => r.gain; // set the reverb mix .1 => r.mix; // set max delay for echo 1000::ms => a.max => b.max => c.max; // set delay for echo 750::ms => a.delay => b.delay => c.delay; // set the initial effect mix 0.0 => a.mix => b.mix => c.mix; // shred to modulate the mix fun void echo_Shred( ) { 0.0 => float decider => float mix => float old => float inc; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .35 ) 0.0 => mix; else if( decider < .55 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => int n; // time loop while( n-- ) { // set the mix for a, b, c old + inc => old => a.mix => b.mix => c.mix; 1::ms => now; } // remember the old mix => old; // let time pass until the next iteration Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ echo_Shred(); // scale [ 0, 2, 4, 7, 9 ] @=> int scale[]; // our main loop while( true ) { // position Std.rand2f( 0.2, 0.8 ) => karp.pickupPosition; // frequency... scale[Std.rand2(0,scale.cap()-1)] => int freq; 220.0 * Math.pow( 1.05946, (Std.rand2(0,2)*12) +freq ) => karp.freq; // pluck it! 0.0 => karp.stretch; Std.rand2f( 0.2, 0.9 ) => karp.pluck; if( Std.randf() > 0.8 ) { 500::ms => now; } else if( Std.randf() > .85 ) { 250::ms => now; } else if( Std.randf() > -0.9 ) { .125::second => now; } else { 1 => int i => int pick_dir; // how many times 4 * Std.rand2( 1, 5 ) => int pick; 0.0 => float pluck; 0.7 / pick => float inc; // time loop for( ; i < pick; i++ ) { 75::ms => now; Std.rand2f(.2,.3) + i*inc => pluck; i * 0.025 => karp.stretch; pluck + -.2 * pick_dir => karp.pluck; // simulate pluck direction !pick_dir => pick_dir; } // let time pass for final pluck 75::ms => now; } } chuck-1.2.0.8.dfsg/examples/stk/stifkarp.ck0000644000175000017500000000151110600421722017116 0ustar piempiem// STK StifKarp // patch StifKarp m => JCRev r => dac; .75 => r.gain; .05 => r.mix; // our notes [ 61, 63, 65, 66, 68, 66, 65, 63 ] @=> int notes[]; // infinite time-loop while( true ) { Std.rand2f( 0, 1 ) => m.pickupPosition; Std.rand2f( 0, 1 ) => m.sustain; Std.rand2f( 0, 1 ) => m.stretch; <<< "---", "" >>>; <<< "pickup:", m.pickupPosition() >>>; <<< "sustain:", m.sustain() >>>; <<< "stretch:", m.stretch() >>>; // factor Std.rand2f( 1, 4 ) => float factor; for( int i; i < notes.cap(); i++ ) { play( Std.rand2(0,2)*12 + notes[i], Std.rand2f( .6, .9 ) ); 100::ms * factor => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // start the note Std.mtof( note ) => m.freq; velocity => m.pluck; } chuck-1.2.0.8.dfsg/examples/stk/voic-o-form.ck0000644000175000017500000000364510600421722017442 0ustar piempiem// music for replicants // patch VoicForm voc=> JCRev r => Echo a => Echo b => Echo c => dac; // settings 220.0 => voc.freq; 0.95 => voc.gain; .8 => r.gain; .2 => r.mix; 1000::ms => a.max => b.max => c.max; 750::ms => a.delay => b.delay => c.delay; .50 => a.mix => b.mix => c.mix; // shred to modulate the mix fun void vecho_Shred( ) { 0.0 => float decider; 0.0 => float mix; 0.0 => float old; 0.0 => float inc; 0 => int n; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .3 ) 0.0 => mix; else if( decider < .6 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => n; while( n-- ) { old + inc => old; old => a.mix => b.mix => c.mix; 1::ms => now; } mix => old; Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ vecho_Shred(); 0.5 => voc.loudness; 0.01 => voc.vibratoGain; // scale [ 0, 2, 4, 7, 9 ] @=> int scale[]; // our main time loop while( true ) { 2 * Std.rand2( 0,2 ) => int bphon; bphon => voc.phonemeNum; Std.rand2f( 0.6, 0.8 ) => voc.noteOn; if( Std.randf() > 0.7 ) { 1000::ms => now; } else if( Std.randf() > .7 ) { 500::ms => now; } else if( Std.randf() > -0.8 ) { .250::second => now; } else { 0 => int i; 4 * Std.rand2( 1, 4 ) => int pick; 0 => int pick_dir; 0.0 => float pluck; for( ; i < pick; i++ ) { bphon + 1 * pick_dir => voc.phonemeNum; Std.rand2f(.4,.6) + i*.035 => pluck; pluck + 0.0 * pick_dir => voc.noteOn; !pick_dir => pick_dir; 250::ms => now; } } // pentatonic scale[Std.rand2(0,scale.cap()-1)] => int freq; Std.mtof( ( 45 + Std.rand2(0,2) * 12 + freq ) ) => voc.freq; } chuck-1.2.0.8.dfsg/examples/stk/wurley.ck0000644000175000017500000000226210600421722016626 0ustar piempiem// even more music for replicants // patch Wurley voc=> JCRev r => dac; // initial settings 220.0 => voc.freq; 0.95 => voc.gain; .8 => r.gain; .2 => r.mix; // scale [ 0, 3, 7, 8, 11 ] @=> int scale[]; // our main time loop while( true ) { // scale scale[Std.rand2(0,scale.cap()-1)] => int freq; Std.mtof( ( 45 + Std.rand2(0,1) * 12 + freq ) ) => voc.freq; Std.rand2f( 0.6, 0.8 ) => voc.noteOn; if( Std.randf() > 0.8 ) { // 1000::ms => now; repeat( 100 ) { voc.freq() * 1.01 => voc.freq; 10::ms => now; } } else if( Std.randf() > .5 ) { // 500::ms => now; repeat( 50 ) { voc.freq() * .99 => voc.freq; 10::ms => now; } } else if( Std.randf() > -0.8 ) { 250::ms => now; } else { 0 => int i; 2 * Std.rand2( 1, 3 ) => int pick; 0 => int pick_dir; 0.0 => float pluck; for( ; i < pick; i++ ) { Std.rand2f(.4,.6) + i*.035 => pluck; pluck + 0.03 * (i * pick_dir) => voc.noteOn; !pick_dir => pick_dir; 250::ms => now; } } } chuck-1.2.0.8.dfsg/examples/stk/wurley2.ck0000644000175000017500000000343010600421722016706 0ustar piempiem// even more music for replicants // patch Wurley voc=> JCRev r => Echo a => Echo b => Echo c => dac; // initial settings 220.0 => voc.freq; 0.95 => voc.gain; .8 => r.gain; .2 => r.mix; 1000::ms => a.max => b.max => c.max; 750::ms => a.delay => b.delay => c.delay; .50 => a.mix => b.mix => c.mix; // shred to modulate the mix fun void vecho_Shred( ) { 0.0 => float decider; 0.0 => float mix; 0.0 => float old; 0.0 => float inc; 0 => int n; // time loop while( true ) { Std.rand2f(0.0,1.0) => decider; if( decider < .3 ) 0.0 => mix; else if( decider < .6 ) .08 => mix; else if( decider < .8 ) .5 => mix; else .15 => mix; // find the increment (mix-old)/1000.0 => inc; 1000 => n; while( n-- ) { old + inc => old; old => a.mix => b.mix => c.mix; 1::ms => now; } mix => old; Std.rand2(2,6)::second => now; } } // let echo shred go spork ~ vecho_Shred(); // scale [ 0, 3, 7, 8, 11 ] @=> int scale[]; // our main time loop while( true ) { // scale scale[Std.rand2(0,scale.cap()-1)] => int freq; Std.mtof( ( 45 + Std.rand2(0,1) * 12 + freq ) ) => voc.freq; Std.rand2f( 0.6, 0.8 ) => voc.noteOn; if( Std.randf() > 0.7 ) { 1000::ms => now; } else if( Std.randf() > .7 ) { 500::ms => now; } else if( Std.randf() > -0.8 ) { .250::second => now; } else { 0 => int i; 2 * Std.rand2( 1, 3 ) => int pick; 0 => int pick_dir; 0.0 => float pluck; for( ; i < pick; i++ ) { Std.rand2f(.4,.6) + i*.035 => pluck; pluck + 0.03 * (i * pick_dir) => voc.noteOn; !pick_dir => pick_dir; 250::ms => now; } } } chuck-1.2.0.8.dfsg/examples/stk/wurley3.ck0000644000175000017500000000162310600421722016711 0ustar piempiem// polyphonic wurley's // (also see ../midi/polyfony.ck for more polyfony) // the size of the array should be the max number of wurlies // you want to play simultaneously, at any point. Wurley wurlies[3]; // variable to remember the last one played int which; // patch Gain g => dac; .4 => g.gain; // connect the wurlies for( int i; i < wurlies.cap(); i++ ) wurlies[i] => g; // our notes [ 61, 63, 65, 66, 68 ] @=> int notes[]; // infinite time-loop while( true ) { for( int i; i < notes.cap(); i++ ) { play( notes[i], Std.rand2f( .3, .9 ) ); 300::ms => now; } } // basic play function (add more arguments as needed) fun void play( float note, float velocity ) { // first figure which to play // round robin may work ( which + 1 ) % wurlies.cap() => which; // start the note Std.mtof( note ) => wurlies[which].freq; velocity => wurlies[which].noteOn; } chuck-1.2.0.8.dfsg/examples/string/0000755000175000017500000000000010600421722015463 5ustar piempiemchuck-1.2.0.8.dfsg/examples/string/escape.ck0000644000175000017500000000047710600421722017252 0ustar piempiem// escape sequences // newline <<< "line1\nline2", "\n" >>>; // tab <<< "a\tb", "\n" >>>; // audible bell (uh...) <<< "bell!\a", "\n" >>>; // " <<< "->\"<-", "\n" >>>; // end of string <<< "here\0can't see me", "\n" >>>; // wait a bit 200::ms => now; // octal (man ascii) <<< "bell!\007\060---\061\012", "" >>>; chuck-1.2.0.8.dfsg/examples/string/readline.ck0000644000175000017500000000071310600421722017566 0ustar piempiem// this is really hacked: ConsoleInput class to be replaced soon // make a ConsoleInput ConsoleInput in; // tokenizer StringTokenizer tok; // loop while( true ) { // prompt in.prompt( "enter line of text:" ) => now; // read while( in.more() ) { // get it tok.set( in.getLine() ); // print tokens while( tok.more() ) { // print it <<< tok.next(), "" >>>; } } } chuck-1.2.0.8.dfsg/examples/string/strops.ck0000644000175000017500000000240610600421722017336 0ustar piempiem// three strings "hello" => string foo; "hello" => string bar; "there" => string geh; // makeshift assert fun void assert( int condition, string text ) { if( !condition ) { <<< "assertion failed: ", text >>>; me.exit(); } } // equality assert( foo == foo, "1" ); assert( foo == bar, "2" ); assert( "abc" == "abc", "3" ); assert( "hello" == foo, "4" ); assert( foo != geh, "5" ); assert( "x" != "y", "6" ); assert( foo != "there", "7" ); // lt assert( foo < geh, "8" ); assert( foo < "hello!", "9" ); assert( foo <= foo, "10" ); assert( foo <= "there", "11" ); // gt assert( foo > "abc", "12" ); assert( foo > "b", "13" ); assert( foo >= foo, "14" ); assert( foo >= bar, "15" ); // concatention assert( "foo" + "bar" == "foobar", "16" ); "foo" => string s; "bar" +=> s; assert( s == "foobar", "17" ); assert( "bar" + 10 == "bar10", "18" ); assert( "bar" + 10.0 == "bar10.0000", "19" ); assert( 10 + "bar" == "10bar", "20" ); assert( 10.0 + "bar" == "10.0000bar", "21" ); assert( "foo" + "bar" + "cle" == "foobarcle", "22" ); assert( "FoO".lower() == "foo", "23" ); assert( "foo".upper() == "FOO", "24" ); assert( " foo ".trim() == "foo", "25" ); assert( " foo ".ltrim() == "foo ", "26" ); assert( " foo ".rtrim() == " foo", "27" ); <<< "success" >>>; chuck-1.2.0.8.dfsg/examples/string/token.ck0000644000175000017500000000030710600421722017122 0ustar piempiem// the very hacked StringTokenizer // make one StringTokenizer tok; // set the string tok.set( "tokenize me please!" ); // iterate while( tok.more() ) { // print <<< tok.next(), "" >>>; } chuck-1.2.0.8.dfsg/examples/time/0000755000175000017500000000000010600421722015113 5ustar piempiemchuck-1.2.0.8.dfsg/examples/time/time_operations.ck0000644000175000017500000000054410600421722020636 0ustar piempiem// ... // store the current time now => time t1; //value to duration 0.5::second => dur d; <<<"one">>>; //now waits for that duration d => now; <<<"two">>>; //define new duration d * 4.0 => dur four_d; //wait again. four_d => now; <<<"three">>>; now => time t2; t2 - t1 => dur span; <<<"total">>>; <<>>; <<<"relative">>>; <<>>; chuck-1.2.0.8.dfsg/examples/time/time_types.ck0000644000175000017500000000033610600421722017616 0ustar piempiem// 05.ck : time, now, duration // time + duration now + 5::second => time later; // time loop while( now < later ) { // print out the time <<>>; // advance time 1::second => now; } <<<"success">>>; chuck-1.2.0.8.dfsg/examples/type/0000755000175000017500000000000010600421722015136 5ustar piempiemchuck-1.2.0.8.dfsg/examples/type/type_object.ck0000644000175000017500000000023310600421722017762 0ustar piempiem// in contrast to primitive types, we have // objects ( more later ). These will display // a reference address when printed. Object obj; <<>>; chuck-1.2.0.8.dfsg/examples/type/type_primitives.ck0000644000175000017500000000101710600421722020710 0ustar piempiem// quick survey of chuck primitives // <<<>>> will print the type and value of any variable; // integers 1 => int i; <<>>; // modify value and print again... 2 => i; <<>>; // hexadecimal notation 0x22 => i; <<>>; // floats 5.678 => float f; <<>>; // durations are a measure of time // the value we print will be in audio samples. 9.0::second => dur d; <<>>; now => time t; <<>>; // we advance time, and now will change to reflect <<<"waiting 10 seconds...">>>; 10::second => now; <<>>; chuck-1.2.0.8.dfsg/INSTALL0000644000175000017500000000605510600421722013376 0ustar piempiemChucK : Build Instructions version: 1.2.x.x (dracula) --- ChucK home: http://chuck.cs.princeton.edu/ Got questions? http://chuck.cs.princeton.edu/community.html email us: gewang@cs.princeton.edu online version of this document: http://chuck.cs.princeton.edu/doc/build/ --- If you are using the executable, you only need to put chuck (osx) or chuck.exe (win32) in your path. On MacOS X (using Terminal): go to the bin/ directory and type: sudo cp chuck /usr/bin/ (enter your password when prompted) sudo chmod 755 /usr/bin/chuck (now you can run chuck from any directory using Terminal) On win32: put bin\chuck.exe in c:\windows\system32\ At this point, you should be able to invoke 'chuck' from either Terminal (in OSX) or 'cmd' under windowsm, from any directory: > chuck [chuck]: no input files... (try --help) (this is the correct output, since we didn't specify the files to run) If that is the case, you can skip the rest of this document. --- We tried to make ChucK as easy as possible to build and re-use. All sources files - headers source for compiler, vm, and audio engine - are in the same directory (they run in the same address space anyway). Platforms differences are abstracted to the lowest level (in part thanks to Gary Scavone). None of the compiler/vm has any OS-depedent code. To build chuck from the source (from scratch): --- 1. Go to the src/ directory (replace chuck-x.x.x.x with the actual directory name): %> cd chuck-x.x.x.x/src/ --- 2. If you type 'make' here, you should get the following message: %> make [chuck build]: please use one of the following configurations: make osx-ppc, make osx-intel, make win32, make linux-oss, make linux-alsa, or make linux-jack Now, type the command corresponding to your platform... for example, for MacOS X (PowerPC): %> make osx-ppc or for MacOS X (Intel): %> make osx-intel etc... --- 3. If you like to install chuck (cp into /usr/bin by default). if you don't like the destination, simply edit the makefile under 'install', or skip this step altogether. (we recommend putting it somewhere in your path, it makes on-the-fly programming easier) # (optional: edit the makefile first) %> make install --- 4. If you haven't gotten any egregous error messages up to this point, then you should be done! There should be a 'chuck' executable in the current directory. For a quick sanity check, execute the following (use './chuck' if chuck is not in your path), and see if you get the same output: %> chuck [chuck]: no input files... (if you do get error messages during compilation, or you run into some other problem - please let us know and we will do our best to provide support) --- 5. You are ready to ChucK. If this is your first time programming in ChucK, you may want to look at the documentation, or take the ChucK Tutorial (in doc/ and online http://chuck.cs.princeton.edu/doc/). ThanK you very much. Go forth and ChucK - email us for support or to make a suggestion or to call us idiots. Ge + Perry chuck-1.2.0.8.dfsg/PROGRAMMER0000644000175000017500000000032710600421722013737 0ustar piempiem--- ChucK Programmers's Guide current version of this document: http://chuck.cs.princeton.edu/doc/language/ http://chuck.cs.princeton.edu/doc/program/ chuck home: http://chuck.cs.princeton.edu/ --- chuck-1.2.0.8.dfsg/QUICKSTART0000644000175000017500000000027510600421722013760 0ustar piempiem For the ideas and design behind ChucK, read the papers at: http://chuck.cs.princeton.edu/doc/publish/ For the most updated tutorial: http://chuck.cs.princeton.edu/doc/learn/ --- chuck-1.2.0.8.dfsg/README0000644000175000017500000000300010600421722013210 0ustar piempiem ChucK: a Concurrent, On-the-fly, Audio Programming Language ChucK home page: http://chuck.cs.princeton.edu/ --- what is it: ChucK is a general-purpose programming language, intended for real-time audio synthesis and graphics/multimedia programming. It introduces a truly concurrent programming model that embeds timing directly in the program flow. Other potentially useful features include the ability to write/change programs on-the-fly. who it is for: audio/multimedia researchers, developers, composers, and performers what this distribution includes: - ChucK compiler - ChucK virtual machine - tutorials and documentation - license + other information supported platforms: - MacOS X (CoreAudio) - Linux (ALSA/OSS) - Windows/Cygwin (DirectSound) authors: see AUTHORS ChucK home page: http://chuck.cs.princeton.edu/ ChucK documentation: http://chuck.cs.princeton.edu/doc/ Princeton Sound Lab: http://soundlab.cs.princeton.edu/ --- *** QUICK START *** Visit the ChucK home page (http://chuck.cs.princeton.edu/) - the ChucK tutorial - documentation - developer's guide - programmer's guide - publications - HTML version: (http://chuck.cs.princeton.edu/doc/) (we recommend reading HTML version) - TEXT only documents: README - this document COPYING/AUTHORS/THANKS - info INSTALL - build and install instructions QUICKSTART - quick start for ChucK DEVELOPER - developer's guide PROGRAMMER - programmer's guide TODO - list of DONE and TODO chuck-1.2.0.8.dfsg/src/0000755000175000017500000000000010612371007013131 5ustar piempiemchuck-1.2.0.8.dfsg/src/chuck.lex0000644000175000017500000002302410600421722014736 0ustar piempiem D [0-9] L [a-zA-Z_] H [a-fA-F0-9] E [Ee][+-]?{D}+ FS (f|F|l|L) IS (u|U|l|L)* %{ /*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck.yy.c // desc: chuck lexer // // author: Ge Wang (gewang.cs.princeton.edu) - generated by lex // Perry R. Cook (prc@cs.princeton.edu) // // based on the ansi C grammar by Jeff Lee, maintained by Jutta Degener // // date: Summer 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_utils.h" #include "chuck_absyn.h" #include "chuck_errmsg.h" #ifndef __PLATFORM_WIN32__ #include "chuck.tab.h" #else #include "chuck_win32.h" #endif // globals extern YYSTYPE yylval; int char_pos = 1; // define error handling #define YY_FATAL_ERROR(msg) EM_error2( 0, msg ) #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif int yywrap(void); void adjust(); c_str strip_lit( c_str str ); c_str alloc_str( c_str str ); long htol( c_str str ); int comment(); int block_comment(); #if defined(_cplusplus) || defined(__cplusplus) } #endif // yywrap() int yywrap( void ) { char_pos = 1; return 1; } // adjust() void adjust() { EM_tokPos = char_pos; char_pos += yyleng; } // strip c_str strip_lit( c_str str ) { str[strlen(str)-1] = '\0'; return str+1; } // alloc_str() c_str alloc_str( c_str str ) { c_str s = (c_str)malloc( strlen(str) + 1 ); strcpy( s, str ); return s; } // to long long htol( c_str str ) { char * c = str; unsigned long n = 0; // skip over 0x c += 2; while( *c ) { n <<= 4; switch( *c ) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': n += *c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': n += *c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': n += *c - 'A' + 10; break; } c++; } return n; } // block comment hack (thanks to unput/yytext_ptr inconsistency) #define block_comment_hack loop: \ while ((c = input()) != '*' && c != 0 && c != EOF ) \ if( c == '\n' ) EM_newline(); \ if( c == EOF ) adjust(); \ else if( (c1 = input()) != '/' && c != 0 ) \ { \ unput(c1); \ goto loop; \ } \ if( c != 0 ) adjust(); // comment hack #define comment_hack \ while ((c = input()) != '\n' && c != '\r' && c != 0 && c != EOF ); \ if (c != 0) { \ adjust(); \ if (c == '\n') EM_newline(); \ } %} %% "//" { char c; adjust(); comment_hack; continue; } "/*" { char c, c1; adjust(); block_comment_hack; continue; } " " { adjust(); continue; } "\t" { adjust(); continue; } "\r\n" { adjust(); EM_newline(); continue; } "\n" { adjust(); EM_newline(); continue; } "++" { adjust(); return PLUSPLUS; } "--" { adjust(); return MINUSMINUS; } "," { adjust(); return COMMA; } ":" { adjust(); return COLON; } "." { adjust(); return DOT; } "+" { adjust(); return PLUS; } "-" { adjust(); return MINUS; } "*" { adjust(); return TIMES; } "/" { adjust(); return DIVIDE; } "%" { adjust(); return PERCENT; } "#" { adjust(); return POUND; } "$" { adjust(); return DOLLAR; } "::" { adjust(); return COLONCOLON; } "==" { adjust(); return EQ; } "!=" { adjust(); return NEQ; } "<" { adjust(); return LT; } ">" { adjust(); return GT; } "<=" { adjust(); return LE; } ">=" { adjust(); return GE; } "&&" { adjust(); return AND; } "||" { adjust(); return OR; } "&" { adjust(); return S_AND; } "|" { adjust(); return S_OR; } "^" { adjust(); return S_XOR; } ">>" { adjust(); return SHIFT_RIGHT; } "<<" { adjust(); return SHIFT_LEFT; } "=" { adjust(); return ASSIGN; } "(" { adjust(); return LPAREN; } ")" { adjust(); return RPAREN; } "[" { adjust(); return LBRACK; } "]" { adjust(); return RBRACK; } "{" { adjust(); return LBRACE; } "}" { adjust(); return RBRACE; } ";" { adjust(); return SEMICOLON; } "?" { adjust(); return QUESTION; } "!" { adjust(); return EXCLAMATION; } "~" { adjust(); return TILDA; } for { adjust(); return FOR; } while { adjust(); return WHILE; } until { adjust(); return UNTIL; } repeat { adjust(); return LOOP; } continue { adjust(); return CONTINUE; } break { adjust(); return BREAK; } if { adjust(); return IF; } else { adjust(); return ELSE; } do { adjust(); return DO; } "<<<" { adjust(); return L_HACK; } ">>>" { adjust(); return R_HACK; } return { adjust(); return RETURN; } function { adjust(); return FUNCTION; } fun { adjust(); return FUNCTION; } new { adjust(); return NEW; } class { adjust(); return CLASS; } interface { adjust(); return INTERFACE; } extends { adjust(); return EXTENDS; } implements { adjust(); return IMPLEMENTS; } public { adjust(); return PUBLIC; } protected { adjust(); return PROTECTED; } private { adjust(); return PRIVATE; } static { adjust(); return STATIC; } pure { adjust(); return ABSTRACT; } const { adjust(); return CONST; } spork { adjust(); return SPORK; } typeof { adjust(); return TYPEOF; } "=>" { adjust(); return CHUCK; } "=<" { adjust(); return UNCHUCK; } "!=>" { adjust(); return UNCHUCK; } "@=>" { adjust(); return AT_CHUCK; } "+=>" { adjust(); return PLUS_CHUCK; } "-=>" { adjust(); return MINUS_CHUCK; } "*=>" { adjust(); return TIMES_CHUCK; } "/=>" { adjust(); return DIVIDE_CHUCK; } "&=>" { adjust(); return S_AND_CHUCK; } "|=>" { adjust(); return S_OR_CHUCK; } "^=>" { adjust(); return S_XOR_CHUCK; } ">>=>" { adjust(); return SHIFT_RIGHT_CHUCK; } "<<=>" { adjust(); return SHIFT_LEFT_CHUCK; } "%=>" { adjust(); return PERCENT_CHUCK; } "@" { adjust(); return AT_SYM; } "@@" { adjust(); return ATAT_SYM; } 0[xX][0-9a-fA-F]+{IS}? { adjust(); yylval.ival=htol(yytext); return NUM; } 0[cC][0-7]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; } [0-9]+{IS}? { adjust(); yylval.ival=atoi(yytext); return NUM; } ([0-9]+"."[0-9]*)|([0-9]*"."[0-9]+) { adjust(); yylval.fval=atof(yytext); return FLOAT; } [A-Za-z_][A-Za-z0-9_]* { adjust(); yylval.sval=alloc_str(yytext); return ID; } \"(\\.|[^\\"])*\" { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; } . { adjust(); EM_error( EM_tokPos, "illegal token" ); } %% /* // comment int comment() { char c; while ((c = yyinput()) != '\n' && c != '\r' && c != 0 && c != EOF ); if (c != 0) { adjust(); if (c == '\n') EM_newline(); } return 0; } // block comment int block_comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0 && c != EOF ) if( c == '\n' ) EM_newline(); if( c == EOF ) { adjust(); return 1; } if( (c1 = yyinput()) != '/' && c != 0 ) { unput(c1); goto loop; } if( c != 0 ) adjust(); return 0; } */ chuck-1.2.0.8.dfsg/src/chuck.y0000644000175000017500000005367510600421722014435 0ustar piempiem%{ /*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck.tab.c // desc: chuck parser // // author: Ge Wang (gewang@cs.princeton.edu) - generated by yacc // Perry R. Cook (prc@cs.princeton.edu) // // based in part on the ansi C grammar by Jeff Lee, maintained by Jutta Degener // // date: Summer 2002 //----------------------------------------------------------------------------- #include #include #include #include "chuck_utils.h" #include "chuck_errmsg.h" #include "chuck_absyn.h" // function int yylex( void ); void yyerror( char *s ) { EM_error( EM_tokPos, "%s", s ); } a_Program g_program = NULL; %} %union { int pos; int ival; double fval; c_str sval; a_Program program; a_Section program_section; a_Stmt_List stmt_list; a_Class_Def class_def; a_Class_Ext class_ext; a_Class_Body class_body; a_Stmt stmt; a_Exp exp; a_Func_Def func_def; a_Var_Decl_List var_decl_list; a_Var_Decl var_decl; a_Type_Decl type_decl; a_Arg_List arg_list; a_Id_List id_list; a_Array_Sub array_sub; }; // expect 35 shift/reduce conflicts %expect 35 %token ID STRING_LIT %token NUM %token FLOAT %token POUND COMMA COLON SEMICOLON LPAREN RPAREN LBRACK RBRACK LBRACE RBRACE DOT PLUS MINUS TIMES DIVIDE PERCENT EQ NEQ LT LE GT GE AND OR ASSIGN IF THEN ELSE WHILE FOR DO LOOP BREAK CONTINUE NULL_TOK FUNCTION RETURN QUESTION EXCLAMATION S_OR S_AND S_XOR PLUSPLUS MINUSMINUS DOLLAR SIMULT PATTERN CODE TRANSPORT HOST TIME WHENEVER NEXT UNTIL EVERY BEFORE AFTER AT AT_SYM ATAT_SYM NEW SIZEOF TYPEOF SAME PLUS_CHUCK MINUS_CHUCK TIMES_CHUCK DIVIDE_CHUCK S_AND_CHUCK S_OR_CHUCK S_XOR_CHUCK SHIFT_RIGHT_CHUCK SHIFT_LEFT_CHUCK PERCENT_CHUCK SHIFT_RIGHT SHIFT_LEFT TILDA CHUCK COLONCOLON S_CHUCK AT_CHUCK LEFT_S_CHUCK UNCHUCK CLASS INTERFACE EXTENDS IMPLEMENTS PUBLIC PROTECTED PRIVATE STATIC ABSTRACT CONST SPORK L_HACK R_HACK %type program %type program_section %type code_segment %type function_definition %type class_definition %type class_body %type class_body2 %type class_ext %type class_decl %type iface_ext %type class_section %type statement_list %type statement //%type label_statement %type loop_statement %type selection_statement %type jump_statement %type expression_statement %type expression %type chuck_expression %type conditional_expression %type logical_or_expression %type logical_and_expression %type inclusive_or_expression %type exclusive_or_expression %type and_expression %type equality_expression %type relational_expression %type shift_expression %type additive_expression %type multiplicative_expression %type tilda_expression %type cast_expression %type unary_expression %type dur_expression %type postfix_expression %type primary_expression %type decl_expression %type unary_operator %type chuck_operator %type var_decl_list %type var_decl %type type_decl_a %type type_decl_b %type type_decl %type type_decl2 %type function_decl %type static_decl %type arg_list %type id_list %type id_dot %type array_exp %type array_empty %start program %% program : program_section { $$ = g_program = new_program( $1, EM_lineNum ); } | program_section program { $$ = g_program = prepend_program( $1, $2, EM_lineNum ); } ; program_section : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); } | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); } | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); } ; class_definition : class_decl CLASS id_list LBRACE class_body RBRACE { $$ = new_class_def( $1, $3, NULL, $5, EM_lineNum ); } | class_decl CLASS id_list class_ext LBRACE class_body RBRACE { $$ = new_class_def( $1, $3, $4, $6, EM_lineNum ); } | class_decl INTERFACE id_list LBRACE class_body RBRACE { $$ = new_iface_def( $1, $3, NULL, $5, EM_lineNum ); } | class_decl INTERFACE id_list iface_ext LBRACE class_body RBRACE { $$ = new_iface_def( $1, $3, $4, $6, EM_lineNum ); } ; class_ext : IMPLEMENTS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); } | IMPLEMENTS id_list EXTENDS id_dot { $$ = new_class_ext( $4, $2, EM_lineNum ); } | EXTENDS id_dot { $$ = new_class_ext( $2, NULL, EM_lineNum ); } | EXTENDS id_dot IMPLEMENTS id_list { $$ = new_class_ext( $2, $4, EM_lineNum ); } ; class_body : class_body2 { $$ = $1; } | { $$ = NULL; } ; class_body2 : class_section { $$ = new_class_body( $1, EM_lineNum ); } | class_section class_body2 { $$ = prepend_class_body( $1, $2, EM_lineNum ); } ; class_section : statement_list { $$ = new_section_stmt( $1, EM_lineNum ); } | function_definition { $$ = new_section_func_def( $1, EM_lineNum ); } | class_definition { $$ = new_section_class_def( $1, EM_lineNum ); } ; iface_ext : EXTENDS id_list { $$ = new_class_ext( NULL, $2, EM_lineNum ); } ; id_list : ID { $$ = new_id_list( $1, EM_lineNum ); } | ID COMMA id_list { $$ = prepend_id_list( $1, $3, EM_lineNum ); } ; id_dot : ID { $$ = new_id_list( $1, EM_lineNum ); } | ID DOT id_dot { $$ = prepend_id_list( $1, $3, EM_lineNum ); } ; function_definition : function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN code_segment { $$ = new_func_def( $1, $2, $3, $4, $6, $8, EM_lineNum ); } | function_decl static_decl type_decl2 ID LPAREN RPAREN code_segment { $$ = new_func_def( $1, $2, $3, $4, NULL, $7, EM_lineNum ); } | function_decl static_decl type_decl2 ID LPAREN arg_list RPAREN SEMICOLON { $$ = new_func_def( $1, $2, $3, $4, $6, NULL, EM_lineNum ); } | function_decl static_decl type_decl2 ID LPAREN RPAREN SEMICOLON { $$ = new_func_def( $1, $2, $3, $4, NULL, NULL, EM_lineNum ); } ; class_decl : PUBLIC { $$ = ae_key_public; } | PRIVATE { $$ = ae_key_private; } | { $$ = ae_key_private; } ; function_decl : FUNCTION { $$ = ae_key_func; } | PUBLIC { $$ = ae_key_public; } | PROTECTED { $$ = ae_key_protected; } | PRIVATE { $$ = ae_key_private; } ; static_decl : STATIC { $$ = ae_key_static; } | ABSTRACT { $$ = ae_key_abstract; } | { $$ = ae_key_instance; } ; type_decl_a : ID { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 0, EM_lineNum ); } | ID AT_SYM { $$ = new_type_decl( new_id_list( $1, EM_lineNum ), 1, EM_lineNum ); } ; type_decl_b : LT id_dot GT { $$ = new_type_decl( $2, 0, EM_lineNum ); } | LT id_dot GT AT_SYM { $$ = new_type_decl( $2, 1, EM_lineNum ); } ; //type_decl_c // : LPAREN id_dot RPAREN { $$ = new_type_decl( $3, 0, EM_lineNum ); } // // | LPAREN id_dot RPAREN AT_SYM { $$ = new_type_decl( $1, 1, EM_lineNum ); } // ; type_decl : type_decl_a { $$ = $1; } | type_decl_b { $$ = $1; } // | type_decl_c { $$ = $1; } ; type_decl2 : type_decl { $$ = $1; } | type_decl array_empty { $$ = add_type_decl_array( $1, $2, EM_lineNum ); } ; arg_list : type_decl var_decl { $$ = new_arg_list( $1, $2, EM_lineNum ); } | type_decl var_decl COMMA arg_list { $$ = prepend_arg_list( $1, $2, $4, EM_lineNum ); } ; statement_list : statement { $$ = new_stmt_list( $1, EM_lineNum ); } | statement statement_list { $$ = prepend_stmt_list( $1, $2, EM_lineNum ); } ; statement : expression_statement { $$ = $1; } | loop_statement { $$ = $1; } | selection_statement { $$ = $1; } | jump_statement { $$ = $1; } // | label_statement { } | code_segment { $$ = $1; } ; jump_statement : RETURN SEMICOLON { $$ = new_stmt_from_return( NULL, EM_lineNum ); } | RETURN expression SEMICOLON { $$ = new_stmt_from_return( $2, EM_lineNum ); } | BREAK SEMICOLON { $$ = new_stmt_from_break( EM_lineNum ); } | CONTINUE SEMICOLON { $$ = new_stmt_from_continue( EM_lineNum ); } ; selection_statement : IF LPAREN expression RPAREN statement { $$ = new_stmt_from_if( $3, $5, NULL, EM_lineNum ); } | IF LPAREN expression RPAREN statement ELSE statement { $$ = new_stmt_from_if( $3, $5, $7, EM_lineNum ); } ; loop_statement : WHILE LPAREN expression RPAREN statement { $$ = new_stmt_from_while( $3, $5, EM_lineNum ); } | DO statement WHILE LPAREN expression RPAREN SEMICOLON { $$ = new_stmt_from_do_while( $5, $2, EM_lineNum ); } | FOR LPAREN expression_statement expression_statement RPAREN statement { $$ = new_stmt_from_for( $3, $4, NULL, $6, EM_lineNum ); } | FOR LPAREN expression_statement expression_statement expression RPAREN statement { $$ = new_stmt_from_for( $3, $4, $5, $7, EM_lineNum ); } | UNTIL LPAREN expression RPAREN statement { $$ = new_stmt_from_until( $3, $5, EM_lineNum ); } | DO statement UNTIL LPAREN expression RPAREN SEMICOLON { $$ = new_stmt_from_do_until( $5, $2, EM_lineNum ); } | LOOP LPAREN expression RPAREN statement { $$ = new_stmt_from_loop( $3, $5, EM_lineNum ); } ; code_segment : LBRACE RBRACE { $$ = new_stmt_from_code( NULL, EM_lineNum ); } | LBRACE statement_list RBRACE { $$ = new_stmt_from_code( $2, EM_lineNum ); } ; expression_statement : SEMICOLON { $$ = NULL; } | expression SEMICOLON { $$ = new_stmt_from_expression( $1, EM_lineNum ); } ; expression : chuck_expression { $$ = $1; } | chuck_expression COMMA expression { $$ = prepend_expression( $1, $3, EM_lineNum ); } ; chuck_expression : decl_expression { $$ = $1; } | chuck_expression chuck_operator decl_expression { $$ = new_exp_from_binary( $1, $2, $3, EM_lineNum ); } ; array_exp : LBRACK expression RBRACK { $$ = new_array_sub( $2, EM_lineNum ); } | LBRACK expression RBRACK array_exp { $$ = prepend_array_sub( $4, $2, EM_lineNum ); } ; array_empty : LBRACK RBRACK { $$ = new_array_sub( NULL, EM_lineNum ); } | array_empty LBRACK RBRACK { $$ = prepend_array_sub( $1, NULL, EM_lineNum ); } ; decl_expression : conditional_expression { $$ = $1; } | type_decl var_decl_list { $$ = new_exp_decl( $1, $2, 0, EM_lineNum ); } | STATIC type_decl var_decl_list { $$ = new_exp_decl( $2, $3, 1, EM_lineNum ); } | SAME var_decl_list { $$ = new_exp_decl( NULL, $2, 0, EM_lineNum ); } | STATIC SAME var_decl_list { $$ = new_exp_decl( NULL, $3, 1, EM_lineNum ); } ; var_decl_list : var_decl { $$ = new_var_decl_list( $1, EM_lineNum ); } | var_decl COMMA var_decl_list { $$ = prepend_var_decl_list( $1, $3, EM_lineNum ); } ; var_decl : ID { $$ = new_var_decl( $1, NULL, EM_lineNum ); } | ID array_exp { $$ = new_var_decl( $1, $2, EM_lineNum ); } | ID array_empty { $$ = new_var_decl( $1, $2, EM_lineNum ); } ; chuck_operator : CHUCK { $$ = ae_op_chuck; } | AT_CHUCK { $$ = ae_op_at_chuck; } | PLUS_CHUCK { $$ = ae_op_plus_chuck; } | MINUS_CHUCK { $$ = ae_op_minus_chuck; } | TIMES_CHUCK { $$ = ae_op_times_chuck; } | DIVIDE_CHUCK { $$ = ae_op_divide_chuck; } | SHIFT_RIGHT_CHUCK { $$ = ae_op_shift_right_chuck; } | SHIFT_LEFT_CHUCK { $$ = ae_op_shift_left_chuck; } | PERCENT_CHUCK { $$ = ae_op_percent_chuck; } | UNCHUCK { $$ = ae_op_unchuck; } | S_AND_CHUCK { $$ = ae_op_s_and_chuck; } | S_OR_CHUCK { $$ = ae_op_s_or_chuck; } | S_XOR_CHUCK { $$ = ae_op_s_xor_chuck; } ; conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression QUESTION expression COLON conditional_expression { $$ = new_exp_from_if( $1, $3, $5, EM_lineNum ); } ; logical_or_expression : logical_and_expression { $$ = $1; } | logical_or_expression OR logical_and_expression { $$ = new_exp_from_binary( $1, ae_op_or, $3, EM_lineNum ); } ; logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND inclusive_or_expression { $$ = new_exp_from_binary( $1, ae_op_and, $3, EM_lineNum ); } ; inclusive_or_expression : exclusive_or_expression { $$ = $1; } | inclusive_or_expression S_OR exclusive_or_expression { $$ = new_exp_from_binary( $1, ae_op_s_or, $3, EM_lineNum ); } ; exclusive_or_expression : and_expression { $$ = $1; } | exclusive_or_expression S_XOR and_expression { $$ = new_exp_from_binary( $1, ae_op_s_xor, $3, EM_lineNum ); } ; and_expression : equality_expression { $$ = $1; } | and_expression S_AND equality_expression { $$ = new_exp_from_binary( $1, ae_op_s_and, $3, EM_lineNum ); } ; equality_expression : relational_expression { $$ = $1; } | equality_expression EQ relational_expression { $$ = new_exp_from_binary( $1, ae_op_eq, $3, EM_lineNum ); } | equality_expression NEQ relational_expression { $$ = new_exp_from_binary( $1, ae_op_neq, $3, EM_lineNum ); } ; relational_expression : shift_expression { $$ = $1; } | relational_expression LT shift_expression { $$ = new_exp_from_binary( $1, ae_op_lt, $3, EM_lineNum ); } | relational_expression GT shift_expression { $$ = new_exp_from_binary( $1, ae_op_gt, $3, EM_lineNum ); } | relational_expression LE shift_expression { $$ = new_exp_from_binary( $1, ae_op_le, $3, EM_lineNum ); } | relational_expression GE shift_expression { $$ = new_exp_from_binary( $1, ae_op_ge, $3, EM_lineNum ); } ; shift_expression : additive_expression { $$ = $1; } | shift_expression SHIFT_LEFT additive_expression { $$ = new_exp_from_binary( $1, ae_op_shift_left, $3, EM_lineNum ); } | shift_expression SHIFT_RIGHT additive_expression { $$ = new_exp_from_binary( $1, ae_op_shift_right, $3, EM_lineNum ); } ; additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { $$ = new_exp_from_binary( $1, ae_op_plus, $3, EM_lineNum ); } | additive_expression MINUS multiplicative_expression { $$ = new_exp_from_binary( $1, ae_op_minus, $3, EM_lineNum ); } ; multiplicative_expression : tilda_expression { $$ = $1; } | multiplicative_expression TIMES tilda_expression { $$ = new_exp_from_binary( $1, ae_op_times, $3, EM_lineNum ); } | multiplicative_expression DIVIDE tilda_expression { $$ = new_exp_from_binary( $1, ae_op_divide, $3, EM_lineNum ); } | multiplicative_expression PERCENT tilda_expression { $$ = new_exp_from_binary( $1, ae_op_percent, $3, EM_lineNum ); } ; tilda_expression : cast_expression { $$ = $1; } | tilda_expression TILDA cast_expression { $$ = new_exp_from_binary( $1, ae_op_tilda, $3, EM_lineNum ); } ; cast_expression : unary_expression { $$ = $1; } | cast_expression DOLLAR type_decl { $$ = new_exp_from_cast( $3, $1, EM_lineNum ); } ; unary_expression : dur_expression { $$ = $1; } | PLUSPLUS unary_expression { $$ = new_exp_from_unary( ae_op_plusplus, $2, EM_lineNum ); } | MINUSMINUS unary_expression { $$ = new_exp_from_unary( ae_op_minusminus, $2, EM_lineNum ); } | unary_operator unary_expression { $$ = new_exp_from_unary( $1, $2, EM_lineNum ); } | TYPEOF unary_expression { $$ = new_exp_from_unary( ae_op_typeof, $2, EM_lineNum ); } | SIZEOF unary_expression { $$ = new_exp_from_unary( ae_op_sizeof, $2, EM_lineNum ); } | NEW type_decl { $$ = new_exp_from_unary2( ae_op_new, $2, NULL, EM_lineNum ); } | NEW type_decl array_exp { $$ = new_exp_from_unary2( ae_op_new, $2, $3, EM_lineNum ); } | SPORK TILDA code_segment { $$ = new_exp_from_unary3( ae_op_spork, $3, EM_lineNum ); } ; unary_operator : PLUS { $$ = ae_op_plus; } | MINUS { $$ = ae_op_minus; } | TILDA { $$ = ae_op_tilda; } | EXCLAMATION { $$ = ae_op_exclamation; } | TIMES { $$ = ae_op_times; } | SPORK TILDA { $$ = ae_op_spork; } // | S_AND { $$ = ae_op_s_and; } ; dur_expression : postfix_expression | dur_expression COLONCOLON postfix_expression { $$ = new_exp_from_dur( $1, $3, EM_lineNum ); } ; postfix_expression : primary_expression { $$ = $1; } | postfix_expression array_exp { $$ = new_exp_from_array( $1, $2, EM_lineNum ); } | postfix_expression LPAREN RPAREN { $$ = new_exp_from_func_call( $1, NULL, EM_lineNum ); } | postfix_expression LPAREN expression RPAREN { $$ = new_exp_from_func_call( $1, $3, EM_lineNum ); } | postfix_expression DOT ID { $$ = new_exp_from_member_dot( $1, $3, EM_lineNum ); } | postfix_expression PLUSPLUS { $$ = new_exp_from_postfix( $1, ae_op_plusplus, EM_lineNum ); } | postfix_expression MINUSMINUS { $$ = new_exp_from_postfix( $1, ae_op_minusminus, EM_lineNum ); } ; primary_expression : ID { $$ = new_exp_from_id( $1, EM_lineNum ); } | NUM { $$ = new_exp_from_int( $1, EM_lineNum ); } | FLOAT { $$ = new_exp_from_float( $1, EM_lineNum ); } | STRING_LIT { $$ = new_exp_from_str( $1, EM_lineNum ); } | array_exp { $$ = new_exp_from_array_lit( $1, EM_lineNum ); } | L_HACK expression R_HACK { $$ = new_exp_from_hack( $2, EM_lineNum ); } | LPAREN expression RPAREN { $$ = $2; } | LPAREN RPAREN { $$ = new_exp_from_nil( EM_lineNum ); } ; chuck-1.2.0.8.dfsg/src/chuck_absyn.cpp0000644000175000017500000005043610600421722016133 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_absyn.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_absyn.h" #include "chuck_utils.h" a_Program new_program( a_Section section, int pos ) { a_Program a = (a_Program)checked_malloc( sizeof( struct a_Program_ ) ); a->section = section; a->linepos = pos; return a; } a_Program prepend_program( a_Section section, a_Program program, int pos ) { a_Program a = new_program( section, pos ); a->next = program; a->linepos = pos; return a; } a_Section new_section_stmt( a_Stmt_List list, int pos ) { a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_ ) ); a->s_type = ae_section_stmt; a->stmt_list = list; a->linepos = pos; return a; } a_Section new_section_func_def( a_Func_Def func_def, int pos ) { a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) ); a->s_type = ae_section_func; a->func_def = func_def; a->linepos = pos; return a; } a_Section new_section_class_def( a_Class_Def class_def, int pos ) { a_Section a = (a_Section)checked_malloc( sizeof( struct a_Section_) ); a->s_type = ae_section_class; a->class_def = class_def; a->linepos = pos; return a; } a_Stmt_List new_stmt_list( a_Stmt stmt, int pos ) { a_Stmt_List a = (a_Stmt_List)checked_malloc( sizeof( struct a_Stmt_List_ ) ); a->stmt = stmt; a->next = NULL; a->linepos = pos; return a; } a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos ) { a_Stmt_List a = new_stmt_list( stmt, pos ); a->next = stmt_list; a->linepos = pos; return a; } a_Stmt new_stmt_from_expression( a_Exp exp, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_exp; a->stmt_exp = exp; a->linepos = pos; return a; } a_Stmt new_stmt_from_code( a_Stmt_List stmt_list, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_code; a->stmt_code.stmt_list = stmt_list; a->linepos = pos; a->stmt_code.linepos = pos; a->stmt_code.self = a; return a; } a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_if; a->stmt_if.cond = cond; a->stmt_if.if_body = if_body; a->stmt_if.else_body = else_body; a->linepos = pos; a->stmt_if.linepos = pos; a->stmt_if.self = a; return a; } a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_while; a->stmt_while.is_do = 0; a->stmt_while.cond = cond; a->stmt_while.body = body; a->linepos = pos; a->stmt_while.linepos = pos; a->stmt_while.self = a; return a; } a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_while; a->stmt_while.is_do = 1; a->stmt_while.cond = cond; a->stmt_while.body = body; a->linepos = pos; a->stmt_while.linepos = pos; a->stmt_while.self = a; return a; } a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_until; a->stmt_until.is_do = 0; a->stmt_until.cond = cond; a->stmt_until.body = body; a->linepos = pos; a->stmt_until.linepos = pos; a->stmt_until.self = a; return a; } a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_until; a->stmt_until.is_do = 1; a->stmt_until.cond = cond; a->stmt_until.body = body; a->linepos = pos; a->stmt_until.linepos = pos; a->stmt_until.self = a; return a; } a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_for; a->stmt_for.c1 = c1; a->stmt_for.c2 = c2; a->stmt_for.c3 = c3; a->stmt_for.body = body; a->linepos = pos; a->stmt_for.linepos = pos; a->stmt_for.self = a; return a; } a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_loop; a->stmt_loop.cond = cond; a->stmt_loop.body = body; a->linepos = pos; a->stmt_loop.linepos = pos; a->stmt_loop.self = a; return a; } a_Stmt new_stmt_from_switch( a_Exp val, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_switch; a->stmt_switch.val = val; a->linepos = pos; a->stmt_switch.linepos = pos; a->stmt_switch.self = a; return a; } a_Stmt new_stmt_from_break( int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_break; a->linepos = pos; a->stmt_break.linepos = pos; a->stmt_break.self = a; return a; } a_Stmt new_stmt_from_continue( int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_continue; a->linepos = pos; a->stmt_continue.linepos = pos; a->stmt_continue.self = a; return a; } a_Stmt new_stmt_from_return( a_Exp exp, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_return; a->stmt_return.val = exp; a->linepos = pos; a->stmt_return.linepos = pos; a->stmt_return.self = a; return a; } a_Stmt new_stmt_from_label( c_str xid, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_gotolabel; a->stmt_gotolabel.name = insert_symbol( xid ); a->linepos = pos; a->stmt_gotolabel.linepos = pos; a->stmt_gotolabel.self = a; return a; } a_Stmt new_stmt_from_case( a_Exp exp, int pos ) { a_Stmt a = (a_Stmt)checked_malloc( sizeof( struct a_Stmt_ ) ); a->s_type = ae_stmt_case; a->stmt_case.exp = exp; a->linepos = pos; a->stmt_case.linepos = pos; a->stmt_case.self = a; return a; } a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos ) { exp->next = list; return exp; } a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_binary; a->s_meta = ae_meta_value; a->binary.lhs = lhs; a->binary.op = oper; a->binary.rhs = rhs; a->linepos = pos; a->binary.linepos = pos; a->binary.self = a; return a; } a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_unary; a->s_meta = exp->s_meta; a->unary.op = oper; a->unary.exp = exp; a->linepos = pos; a->unary.linepos = pos; a->unary.self = a; return a; } a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_unary; a->s_meta = ae_meta_value; a->unary.op = oper; a->unary.type = type; a->unary.array = array; a->linepos = pos; a->unary.linepos = pos; a->unary.self = a; return a; } a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_unary; a->s_meta = ae_meta_value; a->unary.op = oper; a->unary.code = code; a->linepos = pos; a->unary.linepos = pos; a->unary.self = a; return a; } a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_cast; a->s_meta = ae_meta_value; a->cast.type = type; a->cast.exp = exp; a->linepos = pos; a->cast.linepos = pos; a->cast.self = a; return a; } a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_array; a->s_meta = ae_meta_var; a->array.base = base; a->array.indices = indices; a->linepos = pos; a->array.linepos = pos; a->array.self = a; return a; } a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_func_call; a->s_meta = ae_meta_value; a->func_call.func = base; a->func_call.args = args; a->linepos = pos; a->func_call.linepos = pos; a->func_call.self = a; return a; } a_Exp new_exp_from_member_dot( a_Exp base, c_str xid, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_dot_member; a->s_meta = ae_meta_var; a->dot_member.base = base; a->dot_member.xid = insert_symbol( xid ); a->linepos = pos; a->dot_member.linepos = pos; a->dot_member.self = a; return a; } a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_postfix; a->s_meta = ae_meta_var; a->postfix.exp = base; a->postfix.op = op; a->linepos = pos; a->postfix.linepos = pos; a->postfix.self = a; return a; } a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_dur; a->s_meta = ae_meta_value; a->dur.base = base; a->dur.unit = unit; a->linepos = pos; a->dur.linepos = pos; a->dur.self = a; return a; } a_Exp new_exp_from_id( c_str xid, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_var; a->primary.s_type = ae_primary_var; a->primary.var = insert_symbol( xid ); a->linepos = pos; a->primary.linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_int( long num, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_num; a->primary.num = num; a->linepos = pos; a->primary.linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_float( double num, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_float; a->primary.fnum = num; a->linepos = pos; a->primary.linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_str( c_str str, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_str; a->primary.str = str; a->linepos = pos; a->primary.linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_array; a->primary.array = exp_list; a->linepos = pos; a->primary.linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_if( a_Exp cond, a_Exp if_exp, a_Exp else_exp, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_if; a->s_meta = ( ( if_exp->s_meta == ae_meta_var && else_exp->s_meta == ae_meta_var ) ? ae_meta_var : ae_meta_value ); a->exp_if.cond = cond; a->exp_if.if_exp = if_exp; a->exp_if.else_exp = else_exp; a->linepos = pos; a->exp_if.linepos = pos; a->exp_if.self = a; return a; } a_Exp new_exp_decl( a_Type_Decl type, a_Var_Decl_List var_decl_list, int is_static, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_decl; a->s_meta = ae_meta_var; a->decl.type = type; a->decl.var_decl_list = var_decl_list; a->linepos = pos; a->decl.is_static = is_static; a->decl.linepos = pos; a->decl.self = a; return a; } a_Exp new_exp_from_hack( a_Exp exp, int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_hack; a->primary.exp = exp; a->primary.linepos = pos; a->linepos = pos; a->primary.self = a; return a; } a_Exp new_exp_from_nil( int pos ) { a_Exp a = (a_Exp)checked_malloc( sizeof( struct a_Exp_ ) ); a->s_type = ae_exp_primary; a->s_meta = ae_meta_value; a->primary.s_type = ae_primary_nil; a->primary.linepos = pos; a->linepos = pos; a->primary.self = a; return a; } a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos ) { a_Var_Decl a = (a_Var_Decl)checked_malloc( sizeof( struct a_Var_Decl_ ) ); a->xid = insert_symbol(xid); a->array = array; a->linepos = pos; return a; } a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos ) { a_Var_Decl_List a = (a_Var_Decl_List)checked_malloc( sizeof( struct a_Var_Decl_List_ ) ); a->var_decl = var_decl; a->linepos = pos; return a; } a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos ) { a_Var_Decl_List a = new_var_decl_list( var_decl, pos ); a->next = list; return a; } a_Type_Decl new_type_decl( a_Id_List type, int ref, int pos ) { a_Type_Decl a = (a_Type_Decl)checked_malloc( sizeof( struct a_Type_Decl_ ) ); a->xid = type; a->ref = ref; a->linepos = pos; return a; } a_Type_Decl add_type_decl_array( a_Type_Decl a, a_Array_Sub array, int pos ) { assert( a->array == NULL ); a->array = array; return a; } a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos ) { a_Arg_List a = (a_Arg_List)checked_malloc( sizeof( struct a_Arg_List_ ) ); a->type_decl = type_decl; a->var_decl = var_decl; a->next = NULL; a->linepos = pos; return a; } a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, int pos ) { a_Arg_List a = new_arg_list( type_decl, var_decl, pos ); a->next = arg_list; a->linepos = pos; return a; } a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl, a_Type_Decl type_decl, c_str name, a_Arg_List arg_list, a_Stmt code, int pos ) { a_Func_Def a = (a_Func_Def)checked_malloc( sizeof( struct a_Func_Def_ ) ); a->func_decl = func_decl; a->static_decl = static_decl; a->type_decl = type_decl; a->name = insert_symbol( name ); a->arg_list = arg_list; a->s_type = ae_func_user; a->code = code; a->linepos = pos; return a; } a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List name, a_Class_Ext ext, a_Class_Body body, int pos ) { a_Class_Def a = (a_Class_Def)checked_malloc( sizeof( struct a_Class_Def_ ) ); a->decl = class_decl; a->name = name; a->ext = ext; a->body = body; a->linepos = pos; return a; } a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List name, a_Class_Ext ext, a_Class_Body body, int pos ) { a_Class_Def a = new_class_def( class_decl, name, ext, body, pos ); a->iface = 1; return a; } a_Class_Body new_class_body( a_Section section, int pos ) { a_Class_Body a = (a_Class_Body)checked_malloc( sizeof( struct a_Class_Body_ ) ); a->section = section; a->linepos = pos; return a; } a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos ) { a_Class_Body a = new_class_body( section, pos ); a->next = body; a->linepos = pos; return a; } a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos ) { a_Class_Ext a = (a_Class_Ext)checked_malloc( sizeof( struct a_Class_Ext_ ) ); a->extend_id = extend_id; a->impl_list = impl_list; a->linepos = pos; return a; } a_Id_List new_id_list( c_str xid, int pos ) { a_Id_List a = (a_Id_List)checked_malloc( sizeof( struct a_Id_List_ ) ); a->xid = insert_symbol( xid ); a->next = NULL; a->linepos = pos; return a; } a_Id_List prepend_id_list( c_str xid, a_Id_List list, int pos ) { a_Id_List a = new_id_list( xid, pos ); a->next = list; a->linepos = pos; return a; } void clean_exp( a_Exp exp ) { if( !exp ) return; clean_exp( exp->next ); free( exp ); } a_Array_Sub new_array_sub( a_Exp exp, int pos ) { a_Array_Sub a = (a_Array_Sub)checked_malloc( sizeof( struct a_Array_Sub_ ) ); a->exp_list = exp; a->depth = 1; a->linepos = pos; // make sure no multi /* if( exp && exp->next ) { // primary exp? if( is_primary ) { a->exp_list = NULL; a->exp_multi = exp; } else { a->err_num = 1; // multi a->err_pos = exp->linepos; // set error for type-checker goto error; } } */ return a; /* error: clean_exp( exp ); a->exp_list = NULL; return a; */ } a_Array_Sub prepend_array_sub( a_Array_Sub a, a_Exp exp, int pos ) { // if already error if( a->err_num ) goto error; // make sure no multi if( exp && exp->next ) { a->err_num = 1; // multi a->err_pos = exp->linepos; // set error for type-checker goto error; } // empty or not if( (exp && !a->exp_list) || (!exp && a->exp_list) ) { a->err_num = 2; // partial a->err_pos = pos; // set error for type-checker goto error; } // prepend if( exp ) { exp->next = a->exp_list; a->exp_list = exp; } // count a->depth++; return a; error: clean_exp( exp ); return a; } void delete_id_list( a_Id_List x ) { if( !x ) return; a_Id_List curr = x, next = x->next, temp; while( curr ) { temp = curr; curr = next; next = temp->next; free( temp ); } } static const char * op_str[] = { "+", "-", "*", "/", "==", "!=", "<", "<=", ">", ">=", "&&", "||", "|", "&", "<<", ">>", "%", "^", "=>", "+=>", "-=>", "*=>", "/=>", "&=>", "|=>", "^=>", ">>=>", "<<=>", "%=>", "->", "++", "--", "~", "!", "@=>", "=<", "spork ~", "typeof", "sizeof", "new" }; const char * op2str( ae_Operator op ) { t_CKINT index = (t_CKINT)op; if( index < 0 || index >= (t_CKINT)(sizeof(op_str)/sizeof(char *)) ) return "[non-existent operator]"; return op_str[index]; } chuck-1.2.0.8.dfsg/src/chuck_absyn.h0000644000175000017500000003717310600421722015603 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_absyn.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_ABSYN_H__ #define __CHUCK_ABSYN_H__ #include "chuck_symbol.h" #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif // pos typedef int a_Pos; // enum oper typedef enum { ae_op_plus, ae_op_minus, ae_op_times, ae_op_divide, ae_op_eq, ae_op_neq, ae_op_lt, ae_op_le, ae_op_gt, ae_op_ge, ae_op_and, ae_op_or, ae_op_s_or, ae_op_s_and, ae_op_shift_left, ae_op_shift_right, ae_op_percent, ae_op_s_xor, ae_op_chuck, ae_op_plus_chuck, ae_op_minus_chuck, ae_op_times_chuck, ae_op_divide_chuck, ae_op_s_and_chuck, ae_op_s_or_chuck, ae_op_s_xor_chuck, ae_op_shift_right_chuck, ae_op_shift_left_chuck, ae_op_percent_chuck, ae_op_s_chuck, ae_op_plusplus, ae_op_minusminus, ae_op_tilda, ae_op_exclamation, ae_op_at_chuck, ae_op_unchuck, ae_op_spork, ae_op_typeof, ae_op_sizeof, ae_op_new } ae_Operator; const char * op2str( ae_Operator op ); // enum key words typedef enum { ae_key_this, ae_key_me, ae_key_func, ae_key_public, ae_key_protected, ae_key_private, ae_key_static, ae_key_instance, ae_key_abstract } ae_Keyword; //----------------------------------------------------------------------------- // pointer types //----------------------------------------------------------------------------- typedef struct a_Program_ * a_Program; typedef struct a_Section_ * a_Section; typedef struct a_Stmt_List_ * a_Stmt_List; typedef struct a_Class_Def_ * a_Class_Def; typedef struct a_Func_Def_ * a_Func_Def; typedef struct a_Code_Segment_ * a_Code_Segment; typedef struct a_Stmt_ * a_Stmt; typedef struct a_Exp_ * a_Exp; typedef struct a_Exp_Chuck_ * a_Exp_Chuck; typedef struct a_Exp_Binary_ * a_Exp_Binary; typedef struct a_Exp_Cast_ * a_Exp_Cast; typedef struct a_Exp_Unary_ * a_Exp_Unary; typedef struct a_Exp_Postfix_ * a_Exp_Postfix; typedef struct a_Exp_Primary_ * a_Exp_Primary; typedef struct a_Exp_Dur_ * a_Exp_Dur; typedef struct a_Exp_Array_ * a_Exp_Array; typedef struct a_Exp_Func_Call_ * a_Exp_Func_Call; typedef struct a_Exp_Dot_Member_ * a_Exp_Dot_Member; typedef struct a_Exp_If_ * a_Exp_If; typedef struct a_Exp_Decl_ * a_Exp_Decl; typedef struct a_Exp_Hack_ * a_Exp_Hack; typedef struct a_Stmt_Code_ * a_Stmt_Code; typedef struct a_Stmt_If_ * a_Stmt_If; typedef struct a_Stmt_While_ * a_Stmt_While; typedef struct a_Stmt_Until_ * a_Stmt_Until; typedef struct a_Stmt_For_ * a_Stmt_For; typedef struct a_Stmt_Loop_ * a_Stmt_Loop; typedef struct a_Stmt_Switch_ * a_Stmt_Switch; typedef struct a_Stmt_Break_ * a_Stmt_Break; typedef struct a_Stmt_Continue_ * a_Stmt_Continue; typedef struct a_Stmt_Return_ * a_Stmt_Return; typedef struct a_Stmt_Case_ * a_Stmt_Case; typedef struct a_Stmt_GotoLabel_ * a_Stmt_GotoLabel; typedef struct a_Decl_ * a_Decl; typedef struct a_Var_Decl_ * a_Var_Decl; typedef struct a_Var_Decl_List_ * a_Var_Decl_List; typedef struct a_Type_Decl_ * a_Type_Decl; typedef struct a_Arg_List_ * a_Arg_List; typedef struct a_Id_List_ * a_Id_List; typedef struct a_Class_Ext_ * a_Class_Ext; typedef struct a_Class_Body_ * a_Class_Body; typedef struct a_Array_Sub_ * a_Array_Sub; // forward reference for type typedef struct Chuck_Type * t_CKTYPE; typedef struct Chuck_Value * t_CKVALUE; typedef struct Chuck_Func * t_CKFUNC; typedef struct Chuck_Namespace * t_CKNSPC; typedef struct Chuck_VM_Code * t_CKVMCODE; //------------------------------------------------------------------------------ // functions //------------------------------------------------------------------------------ a_Program new_program( a_Section section, int pos ); a_Program prepend_program( a_Section section, a_Program program, int pos ); a_Section new_section_stmt( a_Stmt_List stmt_list, int pos ); a_Section new_section_func_def( a_Func_Def func_def, int pos ); a_Section new_section_class_def( a_Class_Def class_def, int pos ); a_Stmt_List new_stmt_list( a_Stmt stmt, int pos ); a_Stmt_List prepend_stmt_list( a_Stmt stmt, a_Stmt_List stmt_list, int pos ); a_Stmt new_stmt_from_expression( a_Exp exp, int pos ); a_Stmt new_stmt_from_code( a_Stmt_List code, int pos ); a_Stmt new_stmt_from_while( a_Exp cond, a_Stmt body, int pos ); a_Stmt new_stmt_from_do_while( a_Exp cond, a_Stmt body, int pos ); a_Stmt new_stmt_from_until( a_Exp cond, a_Stmt body, int pos ); a_Stmt new_stmt_from_do_until( a_Exp cond, a_Stmt body, int pos ); a_Stmt new_stmt_from_for( a_Stmt c1, a_Stmt c2, a_Exp c3, a_Stmt body, int pos ); a_Stmt new_stmt_from_loop( a_Exp cond, a_Stmt body, int pos ); a_Stmt new_stmt_from_if( a_Exp cond, a_Stmt if_body, a_Stmt else_body, int pos ); a_Stmt new_stmt_from_switch( a_Exp exp, int pos ); a_Stmt new_stmt_from_break( int pos ); a_Stmt new_stmt_from_continue( int pos ); a_Stmt new_stmt_from_return( a_Exp exp, int pos ); a_Stmt new_stmt_from_label( c_str xid, int pos ); a_Stmt new_stmt_from_case( a_Exp exp, int pos ); a_Exp prepend_expression( a_Exp exp, a_Exp list, int pos ); a_Exp new_exp_from_binary( a_Exp lhs, ae_Operator oper, a_Exp rhs, int pos ); a_Exp new_exp_from_unary( ae_Operator oper, a_Exp exp, int pos ); a_Exp new_exp_from_unary2( ae_Operator oper, a_Type_Decl type, a_Array_Sub array, int pos ); a_Exp new_exp_from_unary3( ae_Operator oper, a_Stmt code, int pos ); a_Exp new_exp_from_cast( a_Type_Decl type, a_Exp exp, int pos ); a_Exp new_exp_from_array( a_Exp base, a_Array_Sub indices, int pos ); a_Exp new_exp_from_array_lit( a_Array_Sub exp_list, int pos ); a_Exp new_exp_from_func_call( a_Exp base, a_Exp args, int pos ); a_Exp new_exp_from_member_dot( a_Exp base, c_str member, int pos ); a_Exp new_exp_from_postfix( a_Exp base, ae_Operator op, int pos ); a_Exp new_exp_from_dur( a_Exp base, a_Exp unit, int pos ); a_Exp new_exp_from_id( c_str xid, int pos ); a_Exp new_exp_from_int( long num, int pos ); a_Exp new_exp_from_uint( unsigned long num, int pos ); a_Exp new_exp_from_float( double num, int pos ); a_Exp new_exp_from_str( c_str str, int pos ); a_Exp new_exp_from_if( a_Exp cond, a_Exp lhs, a_Exp rhs, int pos ); a_Exp new_exp_decl( a_Type_Decl type_decl, a_Var_Decl_List var_decl_list, int is_static, int pos ); a_Exp new_exp_from_hack( a_Exp exp, int pos ); a_Exp new_exp_from_nil( int pos ); a_Var_Decl_List new_var_decl_list( a_Var_Decl var_decl, int pos ); a_Var_Decl_List prepend_var_decl_list( a_Var_Decl var_decl, a_Var_Decl_List list, int pos ); a_Var_Decl new_var_decl( c_constr xid, a_Array_Sub array, int pos ); a_Type_Decl new_type_decl( a_Id_List xid, int ref, int pos ); a_Type_Decl add_type_decl_array( a_Type_Decl type_decl, a_Array_Sub array, int pos ); a_Arg_List new_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, int pos ); a_Arg_List prepend_arg_list( a_Type_Decl type_decl, a_Var_Decl var_decl, a_Arg_List arg_list, int pos ); a_Array_Sub new_array_sub( a_Exp exp, int pos ); a_Array_Sub prepend_array_sub( a_Array_Sub array, a_Exp exp, int pos ); a_Class_Def new_class_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos ); a_Class_Body new_class_body( a_Section section, int pos ); a_Class_Body prepend_class_body( a_Section section, a_Class_Body body, int pos ); a_Class_Ext new_class_ext( a_Id_List extend_id, a_Id_List impl_list, int pos ); a_Class_Def new_iface_def( ae_Keyword class_decl, a_Id_List xid, a_Class_Ext ext, a_Class_Body body, int pos ); a_Id_List new_id_list( c_str xid, int pos ); a_Id_List prepend_id_list( c_str xid, a_Id_List list, int pos ); void clean_exp( a_Exp exp ); a_Func_Def new_func_def( ae_Keyword func_decl, ae_Keyword static_decl, a_Type_Decl type_decl, c_str name, a_Arg_List arg_list, a_Stmt code, int pos ); void delete_id_list( a_Id_List x ); //------------------------------------------------------------------------------ // structs //------------------------------------------------------------------------------ struct a_Exp_Binary_ { a_Exp lhs; ae_Operator op; a_Exp rhs; t_CKFUNC ck_func; int linepos; a_Exp self; }; struct a_Exp_Cast_ { a_Type_Decl type; a_Exp exp; int linepos; a_Exp self; }; struct a_Exp_Unary_ { ae_Operator op; a_Exp exp; a_Type_Decl type; a_Array_Sub array; a_Stmt code; int linepos; a_Exp self; }; struct a_Exp_Postfix_ { a_Exp exp; ae_Operator op; int linepos; a_Exp self; }; struct a_Exp_Dur_ { a_Exp base; a_Exp unit; int linepos; a_Exp self; }; struct a_Exp_Array_ { a_Exp base; a_Array_Sub indices; int linepos; a_Exp self; }; struct a_Exp_Func_Call_ { a_Exp func; a_Exp args; t_CKTYPE ret_type; t_CKFUNC ck_func; t_CKVMCODE ck_vm_code; int linepos; a_Exp self; }; struct a_Exp_Dot_Member_ { a_Exp base; t_CKTYPE t_base; S_Symbol xid; int linepos; a_Exp self; }; struct a_Exp_If_ { a_Exp cond; a_Exp if_exp; a_Exp else_exp; int linepos; a_Exp self; }; struct a_Exp_Decl_ { a_Type_Decl type; a_Var_Decl_List var_decl_list; int num_var_decls; int is_static; t_CKTYPE ck_type; int linepos; a_Exp self; }; struct a_Exp_Hack_ { a_Exp exp; int linepos; a_Exp self; }; struct a_Var_Decl_List_ { a_Var_Decl var_decl; a_Var_Decl_List next; int linepos; a_Exp self; }; struct a_Var_Decl_ { S_Symbol xid; a_Var_Decl var_decl; a_Array_Sub array; t_CKVALUE value; void * addr; int linepos; a_Exp self; }; struct a_Type_Decl_ { a_Id_List xid; a_Array_Sub array; int ref; int linepos; /*a_Exp self;*/ }; struct a_Array_Sub_ { t_CKUINT depth; a_Exp exp_list; int linepos; a_Exp self; int err_num; int err_pos; }; struct a_Arg_List_ { a_Type_Decl type_decl; a_Var_Decl var_decl; t_CKTYPE type; a_Arg_List next; int linepos; a_Exp self; }; // enum primary exp type typedef enum { ae_primary_var, ae_primary_num, ae_primary_float, ae_primary_str, ae_primary_array, ae_primary_exp, ae_primary_hack, ae_primary_nil } ae_Exp_Primary_Type; struct a_Exp_Primary_ { ae_Exp_Primary_Type s_type; t_CKVALUE value; union { S_Symbol var; t_CKINT num; t_CKFLOAT fnum; c_str str; a_Array_Sub array; a_Exp exp; }; int linepos; a_Exp self; }; // enum exp type typedef enum { ae_exp_binary = 0, ae_exp_unary, ae_exp_cast, ae_exp_postfix, ae_exp_dur, ae_exp_primary, ae_exp_array, ae_exp_func_call, ae_exp_dot_member, ae_exp_if, ae_exp_decl } ae_Exp_Type; // type meta data typedef enum { ae_meta_value = 0, ae_meta_var } ae_Exp_Meta; struct a_Exp_ { ae_Exp_Type s_type; ae_Exp_Meta s_meta; t_CKTYPE type; t_CKNSPC owner; a_Exp next; t_CKUINT group_size; t_CKTYPE cast_to; t_CKUINT emit_var; // 1 = emit var, 2 = emit var and value union { struct a_Exp_Binary_ binary; struct a_Exp_Unary_ unary; struct a_Exp_Cast_ cast; struct a_Exp_Postfix_ postfix; struct a_Exp_Dur_ dur; struct a_Exp_Primary_ primary; struct a_Exp_Array_ array; struct a_Exp_Func_Call_ func_call; struct a_Exp_Dot_Member_ dot_member; struct a_Exp_If_ exp_if; struct a_Exp_Decl_ decl; struct a_Exp_Hack_ hack; }; int linepos; }; struct a_Stmt_While_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; struct a_Stmt_Until_ { int is_do; a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; struct a_Stmt_For_ { a_Stmt c1; a_Stmt c2; a_Exp c3; a_Stmt body; int linepos; a_Stmt self; }; struct a_Stmt_Loop_ { a_Exp cond; a_Stmt body; int linepos; a_Stmt self; }; struct a_Stmt_Code_ { a_Stmt_List stmt_list; int linepos; a_Stmt self; }; struct a_Stmt_If_ { a_Exp cond; a_Stmt if_body; a_Stmt else_body; int linepos; a_Stmt self; }; struct a_Stmt_Switch_ { a_Exp val; int linepos; a_Stmt self; }; struct a_Stmt_Break_ { int linepos; a_Stmt self; }; struct a_Stmt_Continue_ { int linepos; a_Stmt self; }; struct a_Stmt_Return_ { a_Exp val; int linepos; a_Stmt self; }; struct a_Stmt_Case_ { a_Exp exp; int linepos; a_Stmt self; }; struct a_Stmt_GotoLabel_ { S_Symbol name; int linepos; a_Stmt self; }; // enum values for stmt type typedef enum { ae_stmt_exp, ae_stmt_while, ae_stmt_until, ae_stmt_for, ae_stmt_loop, ae_stmt_if, ae_stmt_code, ae_stmt_switch, ae_stmt_break, ae_stmt_continue, ae_stmt_return, ae_stmt_case, ae_stmt_gotolabel } ae_Stmt_Type; struct a_Stmt_ { ae_Stmt_Type s_type; int skip; union { a_Exp stmt_exp; struct a_Stmt_Code_ stmt_code; struct a_Stmt_While_ stmt_while; struct a_Stmt_Until_ stmt_until; struct a_Stmt_Loop_ stmt_loop; struct a_Stmt_For_ stmt_for; struct a_Stmt_If_ stmt_if; struct a_Stmt_Switch_ stmt_switch; struct a_Stmt_Break_ stmt_break; struct a_Stmt_Continue_ stmt_continue; struct a_Stmt_Return_ stmt_return; struct a_Stmt_Case_ stmt_case; struct a_Stmt_GotoLabel_ stmt_gotolabel; }; int linepos; }; struct a_Stmt_List_ { a_Stmt stmt; a_Stmt_List next; int linepos; }; struct a_Class_Def_ { ae_Keyword decl; a_Id_List name; a_Class_Ext ext; a_Class_Body body; t_CKTYPE type; int iface; t_CKNSPC home; int linepos; }; struct a_Class_Ext_ { a_Id_List extend_id; a_Id_List impl_list; int linepos; }; struct a_Class_Body_ { a_Section section; a_Class_Body next; int linepos; }; struct a_Id_List_ { S_Symbol xid; a_Id_List next; int linepos; }; typedef enum { ae_func_user, ae_func_builtin } ae_Func_Type; // struct t_Func_User_ { int linepos; }; // typedef unsigned int (* builtin_func_ptr)( unsigned int arg ); // struct t_Func_BuiltIn_ { builtin_func_ptr func_ptr; int linepos; }; struct a_Func_Def_ { ae_Keyword func_decl; ae_Keyword static_decl; a_Type_Decl type_decl; t_CKTYPE ret_type; S_Symbol name; a_Arg_List arg_list; a_Stmt code; t_CKFUNC ck_func; unsigned int global; unsigned int s_type; unsigned int stack_depth; void * dl_func_ptr; // should be not NULL iff s_type == ae_func_builtin int linepos; }; // enum values for section types typedef enum { ae_section_stmt, ae_section_func, ae_section_class } ae_Section_Type; struct a_Section_ { ae_Section_Type s_type; union { a_Stmt_List stmt_list; a_Class_Def class_def; a_Func_Def func_def; }; int linepos; }; struct a_Program_ { a_Section section; a_Program next; int linepos; }; #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/chuck_bbq.cpp0000644000175000017500000001742610600421722015565 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_bbq.cpp // desc: implementation // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "chuck_bbq.h" #include #include #include //----------------------------------------------------------------------------- // name: BBQ() // desc: ... //----------------------------------------------------------------------------- BBQ::BBQ() { m_max_midi_device = 1024; m_digi_out = new DigitalOut; m_digi_in = new DigitalIn; m_midi_out = new MidiOut * [m_max_midi_device]; m_midi_in = new MidiIn * [m_max_midi_device]; m_in_count = new DWORD__[m_max_midi_device]; m_out_count = new DWORD__[m_max_midi_device]; memset( m_midi_out, 0, m_max_midi_device * sizeof(MidiOut *) ); memset( m_midi_in, 0, m_max_midi_device * sizeof(MidiIn *) ); memset( m_in_count, 0, m_max_midi_device * sizeof(DWORD__) ); memset( m_out_count, 0, m_max_midi_device * sizeof(DWORD__) ); //m_midi_out[0] = new MidiOut; //m_midi_in[0] = new MidiIn; } //----------------------------------------------------------------------------- // name: ~BBQ() // desc: ... //----------------------------------------------------------------------------- BBQ::~BBQ() { SAFE_DELETE( m_digi_out ); SAFE_DELETE( m_digi_in ); SAFE_DELETE_ARRAY( m_midi_out ); SAFE_DELETE_ARRAY( m_midi_in ); SAFE_DELETE_ARRAY( m_in_count ); SAFE_DELETE_ARRAY( m_out_count ); } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ BBQ::initialize( DWORD__ num_dac_channels, DWORD__ num_adc_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size, DWORD__ num_buffers, DWORD__ dac, DWORD__ adc, DWORD__ block, Chuck_VM * vm_ref, BOOL__ rt_audio, void * callback, void * data ) { set_inouts( adc, dac ); set_chans( num_adc_channels, num_dac_channels ); return Digitalio::initialize( num_dac_channels, num_adc_channels, sampling_rate, bps, buffer_size, num_buffers, block, vm_ref, rt_audio, callback, data ); } //----------------------------------------------------------------------------- // name: set_srate() // desc: ... //----------------------------------------------------------------------------- void BBQ::set_srate( DWORD__ srate ) { Digitalio::m_sampling_rate = srate; } //----------------------------------------------------------------------------- // name: set_bufsize() // desc: ... //----------------------------------------------------------------------------- void BBQ::set_bufsize( DWORD__ bufsize ) { Digitalio::m_buffer_size = bufsize; } //----------------------------------------------------------------------------- // name: set_bufnums() // desc: ... //----------------------------------------------------------------------------- void BBQ::set_numbufs( DWORD__ numbufs ) { Digitalio::m_num_buffers = numbufs; } //----------------------------------------------------------------------------- // name: set_inouts() // desc: ... //----------------------------------------------------------------------------- void BBQ::set_inouts( DWORD__ adc, DWORD__ dac ) { Digitalio::m_dac_n = dac; Digitalio::m_adc_n = adc; } //----------------------------------------------------------------------------- // name: set_chans() // desc: ... //----------------------------------------------------------------------------- void BBQ::set_chans( DWORD__ ins, DWORD__ outs ) { Digitalio::m_num_channels_in = ins; Digitalio::m_num_channels_out = outs; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- void BBQ::shutdown() { Digitalio::shutdown(); } //----------------------------------------------------------------------------- // name: digi_out() // desc: digital out //----------------------------------------------------------------------------- DigitalOut * BBQ::digi_out() { return m_digi_out; } //----------------------------------------------------------------------------- // name: digi_in() // desc: digital in //----------------------------------------------------------------------------- DigitalIn * BBQ::digi_in() { return m_digi_in; } //----------------------------------------------------------------------------- // name: midi_out() // desc: midi out //----------------------------------------------------------------------------- MidiOut * BBQ::midi_out( DWORD__ index ) { if( index >= m_max_midi_device ) return NULL; if( m_midi_out[index] == NULL ) { m_midi_out[index] = new MidiOut; if( !m_midi_out[index]->open( index ) ) { delete m_midi_out[index]; m_midi_out[index] = NULL; m_out_count[index]++; } else m_out_count[index] = 0; } return m_midi_out[index]; } //----------------------------------------------------------------------------- // name: midi_in() // desc: ... //----------------------------------------------------------------------------- MidiIn * BBQ::midi_in( DWORD__ index ) { if( index >= m_max_midi_device ) return NULL; if( m_midi_in[index] == NULL ) { m_midi_in[index] = new MidiIn; if( !m_midi_in[index]->open( index ) ) { delete m_midi_in[index]; m_midi_in[index] = NULL; m_in_count[index]++; } else m_in_count[index] = 0; } return m_midi_in[index]; } //----------------------------------------------------------------------------- // name: RangeMapper() // desc: constructor //----------------------------------------------------------------------------- RangeMapper::RangeMapper( SAMPLE low_l, SAMPLE high_l, SAMPLE low_r, SAMPLE high_r ) { SAMPLE dx = high_l - low_l; if( fabs( (double)dx ) < .000001 ) m_slope = 0.0f; else m_slope = ( high_r - low_r ) / dx; m_inter = high_r - m_slope * high_l; } //----------------------------------------------------------------------------- // name: map() // desc: ... //----------------------------------------------------------------------------- SAMPLE RangeMapper::map( SAMPLE x ) { return m_slope * x + m_inter; } chuck-1.2.0.8.dfsg/src/chuck_bbq.h0000644000175000017500000001132610600421722015223 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_bbq.h // desc: bbq header // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __CHUCK_BBQ_H__ #define __CHUCK_BBQ_H__ // currently ChucK uses RtAudio | __CHUCK_NATIVE_AUDIO__ not in use #if defined(__CHUCK_NATIVE_AUDIO__) #if defined(__LINUX_ALSA__) #include "digiio_alsa.h" #include "midiio_alsa.h" #elif defined(__LINUX_JACK__) #include "digiio_jack.h" #include "midiio_alsa.h" #elif defined(__LINUX_OSS__) #include "digiio_oss.h" #include "midiio_oss.h" #elif defined(__MACOSX_CORE__) #include "digiio_osx.h" #include "midiio_osx.h" #elif defined(__WINDOWS_DS__) #include "digiio_win32.h" #include "midiio_win32.h" #else #error "must define one:\ __LINUX_ALSA__ __LINUX_JACK__ __LINUX_OSS__ __MACOSX_CORE__ __WINDOWS_DS__" #endif #else #include "digiio_rtaudio.h" #include "midiio_rtmidi.h" #if defined(__LINUX_ALSA__) #elif defined(__LINUX_JACK__) #elif defined(__LINUX_OSS__) #elif defined(__MACOSX_CORE__) #elif defined(__WINDOWS_DS__) #elif defined(__WINDOWS_ASIO__) #else #error "must define one:\ __LINUX_ALSA__ __LINUX_JACK__ __LINUX_OSS__ __MACOSX_CORE__ __WINDOWS_DS__" #endif #endif struct Chuck_VM; //----------------------------------------------------------------------------- // name: class BBQ // desc: ... //----------------------------------------------------------------------------- class BBQ { public: BBQ(); ~BBQ(); public: BOOL__ initialize( DWORD__ num_dac_channels, DWORD__ num_adc_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size = BUFFER_SIZE_DEFAULT, DWORD__ num_buffers = NUM_BUFFERS_DEFAULT, DWORD__ dac = 0, DWORD__ adc = 0, DWORD__ block = TRUE, Chuck_VM * vm_ref = NULL, BOOL__ rt_audio = TRUE, void * callback = NULL, void * data = NULL ); void set_srate( DWORD__ srate ); void set_bufsize( DWORD__ bufsize ); void set_numbufs( DWORD__ numbufs ); void set_inouts( DWORD__ adc, DWORD__ dac ); void set_chans( DWORD__ ins, DWORD__ outs ); void shutdown(); public: DigitalOut * digi_out(); DigitalIn * digi_in(); MidiOut * midi_out( DWORD__ index = 0 ); MidiIn * midi_in( DWORD__ index = 0 ); public: DWORD__ in_count( DWORD__ index = 0 ) { return index < m_max_midi_device ? m_in_count[index] : 0; } DWORD__ out_count( DWORD__ index = 0 ) { return index < m_max_midi_device ? m_out_count[index] : 0; } protected: DigitalOut * m_digi_out; DigitalIn * m_digi_in; MidiOut ** m_midi_out; MidiIn ** m_midi_in; DWORD__ * m_in_count; DWORD__ * m_out_count; DWORD__ m_max_midi_device; }; //----------------------------------------------------------------------------- // name: class RangeMapper // desc: ... //----------------------------------------------------------------------------- class RangeMapper { public: RangeMapper( SAMPLE low_l, SAMPLE high_l, SAMPLE low_r, SAMPLE high_r ); public: virtual SAMPLE map( SAMPLE in ); protected: float m_slope; float m_inter; SAMPLE m_low_l; SAMPLE m_high_l; SAMPLE m_low_r; SAMPLE m_high_r; }; #endif chuck-1.2.0.8.dfsg/src/chuck_compile.cpp0000644000175000017500000003674510600421722016456 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_compile.cpp // desc: chuck compile system unifying parser, type checker, and emitter // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2005 - original //----------------------------------------------------------------------------- #include "chuck_compile.h" #include "chuck_lang.h" #include "chuck_errmsg.h" #include "chuck_otf.h" #include "ugen_osc.h" #include "ugen_xxx.h" #include "ugen_filter.h" #include "ugen_stk.h" #include "ulib_machine.h" #include "ulib_math.h" #include "ulib_std.h" #include "ulib_opsc.h" using namespace std; // function prototypes t_CKBOOL load_internal_modules( Chuck_Compiler * compiler ); t_CKBOOL load_module( Chuck_Env * env, f_ck_query query, const char * name, const char * nspc ); //----------------------------------------------------------------------------- // name: Chuck_Compiler() // desc: constructor //----------------------------------------------------------------------------- Chuck_Compiler::Chuck_Compiler() { env = NULL; emitter = NULL; code = NULL; } //----------------------------------------------------------------------------- // name: ~Chuck_Compiler() // desc: destructor //----------------------------------------------------------------------------- Chuck_Compiler::~Chuck_Compiler() { // call shutdown this->shutdown(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize the compiler //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::initialize( Chuck_VM * vm ) { // log EM_log( CK_LOG_SYSTEM, "initializing compiler..." ); // push indent level EM_pushlog(); // allocate the type checker env = type_engine_init( vm ); // add reference env->add_ref(); // allocate the emitter emitter = emit_engine_init( env ); // add reference emitter->add_ref(); // set auto depend to 0 m_auto_depend = FALSE; // load internal libs if( !load_internal_modules( this ) ) goto error; // pop indent EM_poplog(); return TRUE; error: // clean up this->shutdown(); // pop indent EM_poplog(); return FALSE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: shutdown the compiler //----------------------------------------------------------------------------- void Chuck_Compiler::shutdown() { // log EM_log( CK_LOG_SYSTEM, "shutting down compiler..." ) ; // push indent EM_pushlog(); // TODO: free type_engine_shutdown( env ); // emit_engine_shutdown( emitter ); env = NULL; emitter = NULL; code = NULL; m_auto_depend = FALSE; m_recent.clear(); // pop indent EM_poplog(); } //----------------------------------------------------------------------------- // name: set_auto_depend() // desc: auto dependency resolve for types //----------------------------------------------------------------------------- void Chuck_Compiler::set_auto_depend( t_CKBOOL v ) { // log EM_log( CK_LOG_SYSTEM, "type dependency resolution: %s", v ? "AUTO" : "MANUAL" ); m_auto_depend = v; } //----------------------------------------------------------------------------- // name: go() // desc: parse, type-check, and emit a program //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::go( const string & filename, FILE * fd, const char * str_src ) { t_CKBOOL ret = TRUE; Chuck_Context * context = NULL; // check to see if resolve dependencies automatically if( !m_auto_depend ) { // normal ret = this->do_normal( filename, fd, str_src ); return ret; } else // auto { // parse the code if( !chuck_parse( filename.c_str(), fd, str_src ) ) return FALSE; // make the context context = type_engine_make_context( g_program, filename ); if( !context ) return FALSE; // reset the env env->reset(); // load the context if( !type_engine_load_context( env, context ) ) return FALSE; // do entire file if( !do_entire_file( context ) ) { ret = FALSE; goto cleanup; } // get the code if( !(code = context->code()) ) { ret = FALSE; EM_error2( 0, "internal error: context->code() NULL!" ); goto cleanup; } cleanup: // commit if( ret ) env->global()->commit(); // or rollback else env->global()->rollback(); // unload the context from the type-checker if( !type_engine_unload_context( env ) ) { EM_error2( 0, "internal error unloading context...\n" ); return FALSE; } return ret; } } //----------------------------------------------------------------------------- // name: resolve() // desc: resolve type automatically - if auto_depend is off, return FALSE //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::resolve( const string & type ) { t_CKBOOL ret = TRUE; // check auto_depend if( !m_auto_depend ) return FALSE; // look up if name is already parsed return ret; } //----------------------------------------------------------------------------- // name: do_entire_file() // desc: parse, type-check, and emit a program //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_entire_file( Chuck_Context * context ) { // 0th-scan (pass 0) if( !type_engine_scan0_prog( env, g_program, te_do_all ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env, g_program, te_do_all ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env, g_program, te_do_all ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env, context, te_do_all ) ) return FALSE; // emit (pass 4) if( !emit_engine_emit_prog( emitter, g_program ) ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL; return TRUE; } //----------------------------------------------------------------------------- // name: do_only_classes() // desc: compile only classes definitions //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_only_classes( Chuck_Context * context ) { // 0th-scan (pass 0) if( !type_engine_scan0_prog( env, g_program, te_do_classes_only ) ) return FALSE; // 1st-scan (pass 1) if( !type_engine_scan1_prog( env, g_program, te_do_classes_only ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env, g_program, te_do_classes_only ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env, context, te_do_classes_only ) ) return FALSE; // emit (pass 4) if( !(code = emit_engine_emit_prog( emitter, g_program , te_do_classes_only )) ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL; return TRUE; } //----------------------------------------------------------------------------- // name: do_all_except_classes() // desc: compile everything except classes //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_all_except_classes( Chuck_Context * context ) { // 0th scan only deals with classes, so is not needed // 1st-scan (pass 1) if( !type_engine_scan1_prog( env, g_program, te_do_no_classes ) ) return FALSE; // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env, g_program, te_do_no_classes ) ) return FALSE; // check the program (pass 3) if( !type_engine_check_context( env, context, te_do_no_classes ) ) return FALSE; // emit (pass 4) if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_no_classes )) ) return FALSE; // set the state of the context to done context->progress = Chuck_Context::P_ALL; return TRUE; } //----------------------------------------------------------------------------- // name: do_normal() // desc: compile normally without auto-depend //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::do_normal( const string & filename, FILE * fd, const char * str_src ) { t_CKBOOL ret = TRUE; Chuck_Context * context = NULL; // parse the code if( !chuck_parse( filename.c_str(), fd, str_src ) ) return FALSE; // make the context context = type_engine_make_context( g_program, filename ); if( !context ) return FALSE; // reset the env env->reset(); // load the context if( !type_engine_load_context( env, context ) ) return FALSE; // 0th-scan (pass 0) if( !type_engine_scan0_prog( env, g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 1st-scan (pass 1) if( !type_engine_scan1_prog( env, g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env, g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // check the program (pass 3) if( !type_engine_check_context( env, context, te_do_all ) ) { ret = FALSE; goto cleanup; } // emit (pass 4) if( !(code = emit_engine_emit_prog( emitter, g_program, te_do_all )) ) { ret = FALSE; goto cleanup; } cleanup: // commit if( ret ) env->global()->commit(); // or rollback else env->global()->rollback(); // unload the context from the type-checker if( !type_engine_unload_context( env ) ) { EM_error2( 0, "internal error unloading context...\n" ); return FALSE; } return ret; } //----------------------------------------------------------------------------- // name: find_recent_path() // desc: find recent context by path //----------------------------------------------------------------------------- Chuck_Context * Chuck_Compiler::find_recent_path( const string & path ) { return NULL; } //----------------------------------------------------------------------------- // name: find_recent_type() // desc: find recent context by type name //----------------------------------------------------------------------------- Chuck_Context * Chuck_Compiler::find_recent_type( const string & type ) { return NULL; } //----------------------------------------------------------------------------- // name: add_recent_path() // desc: add recent context by path //----------------------------------------------------------------------------- t_CKBOOL Chuck_Compiler::add_recent_path( const string & path, Chuck_Context * context ) { return TRUE; } //----------------------------------------------------------------------------- // name: output() // desc: get the code generated by the last do() //----------------------------------------------------------------------------- Chuck_VM_Code * Chuck_Compiler::output() { return this->code; } //----------------------------------------------------------------------------- // name: load_module() // desc: load a dll and add it //----------------------------------------------------------------------------- t_CKBOOL load_module( Chuck_Env * env, f_ck_query query, const char * name, const char * nspc ) { Chuck_DLL * dll = NULL; t_CKBOOL query_failed = FALSE; // load osc dll = new Chuck_DLL( name ); if( !dll->load( query ) || (query_failed = !dll->query()) || !type_engine_add_dll( env, dll, nspc ) ) { fprintf( stderr, "[chuck]: internal error loading module '%s.%s'...\n", nspc, name ); if( query_failed ) fprintf( stderr, " %s\n", dll->last_error() ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: load_internal_modules() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL load_internal_modules( Chuck_Compiler * compiler ) { // log EM_log( CK_LOG_SEVERE, "loading built-in modules..." ); // push indent level EM_pushlog(); // get env Chuck_Env * env = compiler->env; // make context Chuck_Context * context = type_engine_make_context( NULL, "@[internal]" ); // reset env - not needed since we just created the env env->reset(); // load it type_engine_load_context( env, context ); // load EM_log( CK_LOG_SEVERE, "module osc..." ); load_module( env, osc_query, "osc", "global" ); EM_log( CK_LOG_SEVERE, "module xxx..." ); load_module( env, xxx_query, "xxx", "global" ); EM_log( CK_LOG_SEVERE, "module filter..." ); load_module( env, filter_query, "filter", "global" ); EM_log( CK_LOG_SEVERE, "module STK..." ); load_module( env, stk_query, "stk", "global" ); // load EM_log( CK_LOG_SEVERE, "class 'machine'..." ); if( !load_module( env, machine_query, "Machine", "global" ) ) goto error; machine_init( compiler, otf_process_msg ); EM_log( CK_LOG_SEVERE, "class 'std'..." ); if( !load_module( env, libstd_query, "Std", "global" ) ) goto error; EM_log( CK_LOG_SEVERE, "class 'math'..." ); if( !load_module( env, libmath_query, "Math", "global" ) ) goto error; EM_log( CK_LOG_SEVERE, "class 'opsc'..." ); if( !load_module( env, opensoundcontrol_query, "opsc", "global" ) ) goto error; // if( !load_module( env, net_query, "net", "global" ) ) goto error; if( !init_class_Midi( env ) ) goto error; if( !init_class_MidiRW( env ) ) goto error; if( !init_class_HID( env ) ) goto error; // clear context type_engine_unload_context( env ); // commit what is in the type checker at this point env->global()->commit(); // pop indent level EM_poplog(); return TRUE; error: // probably dangerous: rollback env->global()->rollback(); // clear context type_engine_unload_context( env ); // pop indent level EM_poplog(); return FALSE; } chuck-1.2.0.8.dfsg/src/chuck_compile.h0000644000175000017500000000710010600421722016102 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_compile.h // desc: chuck compile system unifying parser, type checker, and emitter // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2005 - original //----------------------------------------------------------------------------- #ifndef __CHUCK_COMPILE_H__ #define __CHUCK_COMPILE_H__ #include "chuck_def.h" #include "chuck_parse.h" #include "chuck_scan.h" #include "chuck_type.h" #include "chuck_emit.h" #include "chuck_vm.h" //----------------------------------------------------------------------------- // name: struct Chuck_Compiler // desc: the sum of the components in compilation //----------------------------------------------------------------------------- struct Chuck_Compiler { public: // data // type-checking environment Chuck_Env * env; // emitter Chuck_Emitter * emitter; // generated code Chuck_VM_Code * code; // auto-depend flag t_CKBOOL m_auto_depend; // recent map std::map m_recent; public: // to all // contructor Chuck_Compiler(); // destructor virtual ~Chuck_Compiler(); // initialize t_CKBOOL initialize( Chuck_VM * vm ); // shutdown void shutdown(); // set auto depend void set_auto_depend( t_CKBOOL v ); // parse, type-check, and emit a program t_CKBOOL go( const std::string & filename, FILE * fd = NULL, const char * str_src = NULL ); // resolve a type automatically, if auto_depend is on t_CKBOOL resolve( const std::string & type ); // get the code generated from the last go() Chuck_VM_Code * output( ); protected: // internal // do entire file t_CKBOOL do_entire_file( Chuck_Context * context ); // do just class definitions t_CKBOOL do_only_classes( Chuck_Context * context ); // do all excect classes t_CKBOOL do_all_except_classes( Chuck_Context * context ); // do normal compile t_CKBOOL do_normal( const std::string & path, FILE * fd = NULL, const char * str_src = NULL ); // look up in recent Chuck_Context * find_recent_path( const std::string & path ); // look up in recent Chuck_Context * find_recent_type( const std::string & type ); // add to recent t_CKBOOL add_recent_path( const std::string & path, Chuck_Context * context ); }; // call this to detach all open files extern "C" void all_detach(); #endif chuck-1.2.0.8.dfsg/src/chuck_console.cpp0000644000175000017500000000635210600421722016457 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_console.cpp // desc: ... // // author: Spencer Salazar (ssalazar@princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #include "chuck_console.h" #include "util_console.h" //----------------------------------------------------------------------------- // name: Chuck_Console() // desc: ... //----------------------------------------------------------------------------- Chuck_Console::Chuck_Console() { } //----------------------------------------------------------------------------- // name: ~Chuck_Console() // desc: ... //----------------------------------------------------------------------------- Chuck_Console::~Chuck_Console() { } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Console::init() { return TRUE; } //----------------------------------------------------------------------------- // name: nextCommand() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Console::next_command( const string & prompt, string & out ) { // the line read char * line_read = NULL; // read the next line line_read = io_readline( prompt.c_str() ); // check to see if EOF encountered // do we need more return codes to differentiate between // EOF encountered vs. empty line? if( line_read == NULL ) { out = ""; return FALSE; } // check first character if( *line_read != 0 ) io_addhistory( line_read ); // copy the result out = line_read; // free the thing free( line_read ); return TRUE; } //----------------------------------------------------------------------------- // name: nextResult() // desc: ... //----------------------------------------------------------------------------- void Chuck_Console::next_result( const Chuck_Shell_Response &in ) { fputs( in.c_str(), stdout ); } chuck-1.2.0.8.dfsg/src/chuck_console.h0000644000175000017500000000371110600421722016120 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_console.h // desc: ... // // author: Spencer Salazar (ssalazar@princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #ifndef __CHUCK_CONSOLE_H__ #define __CHUCK_CONSOLE_H__ #include "chuck_def.h" #include "chuck_shell.h" //----------------------------------------------------------------------------- // name: class Chuck_Console // desc: for ttyp access to chuck shell //----------------------------------------------------------------------------- class Chuck_Console : public Chuck_Shell_UI { public: Chuck_Console(); virtual ~Chuck_Console(); t_CKBOOL init(); t_CKBOOL next_command( const string &, string &); void next_result(const string &); }; #endif //__CHUCK_CONSOLE_H__ chuck-1.2.0.8.dfsg/src/chuck_def.h0000644000175000017500000001212610600421722015214 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_def.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_DEF_H__ #define __CHUCK_DEF_H__ #include #include #include // types #define t_CKTIME double #define t_CKDUR double #define t_CKFLOAT double #define t_CKDOUBLE double #define t_CKSINGLE float #define t_CKINT long #define t_CKDWORD unsigned long #define t_CKUINT t_CKDWORD #define t_CKBOOL t_CKDWORD #define t_CKBYTE unsigned char #define t_CKVOID void #define t_CKVOIDPTR void * // size #define sz_TIME sizeof(double) #define sz_DUR sizeof(double) #define sz_FLOAT sizeof(double) #define sz_DOUBLE sizeof(double) #define sz_SINGLE sizeof(float) #define sz_INT sizeof(long) #define sz_DWORD sizeof(unsigned long) #define sz_UINT sizeof(t_CKDWORD) #define sz_BOOL sizeof(t_CKDWORD) #define sz_BYTE sizeof(unsigned char) #define sz_VOID 0 #define sz_VOIDPTR sizeof(void *) typedef char * c_str; typedef const char * c_constr; // double // #define CK_S_DOUBLE // sample #ifdef CK_S_DOUBLE #define SAMPLE double #define SILENCE 0.0 #define CK_DDN CK_DDN_DOUBLE #else #define SAMPLE float #define SILENCE 0.0f #define CK_DDN CK_DDN_SINGLE #endif // bool #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif // 3.1415926535897932384626433832795028841971693993751058209749445... #define ONE_PI (3.14159265358979323846) #define TWO_PI (2.0 * ONE_PI) #define SQRT2 (1.41421356237309504880) #ifndef SAFE_DELETE #define SAFE_DELETE(x) do { if(x){ delete x; x = NULL; } } while(0) #define SAFE_DELETE_ARRAY(x) do { if(x){ delete [] x; x = NULL; } } while(0) #define SAFE_RELEASE(x) do { if(x){ x->release(); x = NULL; } } while(0) #define SAFE_ADD_REF(x) do { if(x){ x->add_ref(); } } while(0) #define SAFE_REF_ASSIGN(lhs,rhs) do { SAFE_RELEASE(lhs); (lhs) = (rhs); SAFE_ADD_REF(lhs); } while(0) #endif // max + min #define ck_max(x,y) ( x >= y ? x : y ) #define ck_min(x,y) ( x <= y ? x : y ) // dedenormal #define CK_DDN_SINGLE(f) f = ( f >= 0 ? \ ( ( f > (t_CKSINGLE)1e-15 && f < (t_CKSINGLE)1e15 ) ? f : (t_CKSINGLE)0.0 ) : \ ( ( f < (t_CKSINGLE)-1e-15 && f > (t_CKSINGLE)-1e15 ) ? f : (t_CKSINGLE)0.0 ) ) #define CK_DDN_DOUBLE(f) f = ( f >= 0 ? \ ( ( f > (t_CKDOUBLE)1e-15 && f < (t_CKDOUBLE)1e15 ) ? f : 0.0 ) : \ ( ( f < (t_CKDOUBLE)-1e-15 && f > (t_CKDOUBLE)-1e15 ) ? f : 0.0 ) ) // tracking #if defined(__CHUCK_STAT_TRACK__) #define CK_TRACK( stmt ) stmt #else #define CK_TRACK( stmt ) #endif #ifdef __MACOSX_CORE__ #define __PLATFORM_MACOSX__ #endif #if defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) || defined(__LINUX_OSS__) #define __PLATFORM_LINUX__ #endif #ifdef __PLATFORM_WIN32__ #ifndef usleep #define usleep(x) Sleep( (x / 1000 <= 0 ? 1 : x / 1000) ) #endif #pragma warning (disable : 4996) // stdio deprecation #pragma warning (disable : 4786) // stl debug info #pragma warning (disable : 4312) // type casts from void* #pragma warning (disable : 4311) // type casts to void* #pragma warning (disable : 4244) // truncation #pragma warning (disable : 4068) // unknown pragma #endif #endif chuck-1.2.0.8.dfsg/src/chuck_dl.cpp0000644000175000017500000010466310600421722015420 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_dl.cpp // desc: chuck dynamic linking // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ari Lazier (alazier@cs.princeton.edu) // mac os code based on apple's open source // // date: spring 2004 - 1.1 // spring 2005 - 1.2 //----------------------------------------------------------------------------- #include "chuck_dl.h" #include "chuck_errmsg.h" #include "chuck_bbq.h" using namespace std; //----------------------------------------------------------------------------- // internal implementation of query functions //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: ck_setname() // desc: set the name of the module //----------------------------------------------------------------------------- void CK_DLL_CALL ck_setname( Chuck_DL_Query * query, const char * name ) { // set the name query->dll_name = name; } //----------------------------------------------------------------------------- // name: ck_begin_class() // desc: begin class/namespace, can be nexted //----------------------------------------------------------------------------- void CK_DLL_CALL ck_begin_class( Chuck_DL_Query * query, const char * name, const char * parent ) { // push query->stack.push_back( query->curr_class ); // allocate Chuck_DL_Class * c = new Chuck_DL_Class; // add class if( query->curr_class ) // recursive query->curr_class->classes.push_back( c ); else // first level query->classes.push_back( c ); // remember info c->name = name; c->parent = parent; // curr query->curr_class = c; query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_add_ctor() // desc: add constructor, can be followed by add_arg //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_ctor( Chuck_DL_Query * query, f_ctor ctor ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_ctor invoked without begin_class..." ); return; } // allocate Chuck_DL_Func * f = new Chuck_DL_Func; f->name = "[ctor]"; f->type = "void"; f->ctor = ctor; // add query->curr_class->ctors.push_back( f ); query->curr_func = f; } //----------------------------------------------------------------------------- // name: ck_add_dtor() // add destructor, no args allowed //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_dtor( Chuck_DL_Query * query, f_dtor dtor ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_dtor invoked without begin_class..." ); return; } // make sure there are no duplicates if( query->curr_class->dtor ) { // error EM_error2( 0, "class import: multiple dtor added ..." ); return; } // allocate Chuck_DL_Func * f = new Chuck_DL_Func; f->name = "[dtor]"; f->type = "void"; f->dtor = dtor; // add query->curr_class->dtor = f; // set query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_add_mfun() // desc: add member function, can be followed by add_arg //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_mfun( Chuck_DL_Query * query, f_mfun addr, const char * type, const char * name ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_mfun invoked without begin_class..." ); return; } // allocate Chuck_DL_Func * f = new Chuck_DL_Func; f->name = name; f->type = type; f->mfun = addr; // add query->curr_class->mfuns.push_back( f ); query->curr_func = f; } //----------------------------------------------------------------------------- // name: ck_add_sfun() // desc: add static function, can be followed by add_arg //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_sfun( Chuck_DL_Query * query, f_sfun addr, const char * type, const char * name ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_sfun invoked without begin_class..." ); return; } // allocate Chuck_DL_Func * f = new Chuck_DL_Func; f->name = name; f->type = type; f->sfun = addr; // add query->curr_class->sfuns.push_back( f ); query->curr_func = f; } //----------------------------------------------------------------------------- // name: ck_add_mvar() // desc: add member var //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_mvar( Chuck_DL_Query * query, const char * type, const char * name, t_CKBOOL is_const ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_mvar invoked without begin_class..." ); return; } // allocate Chuck_DL_Value * v = new Chuck_DL_Value; v->name = name; v->type = type; v->is_const = is_const; // add query->curr_class->mvars.push_back( v ); query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_add_svar() // desc: add static var //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_svar( Chuck_DL_Query * query, const char * type, const char * name, t_CKBOOL is_const, void * addr ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_svar invoked without begin_class..." ); return; } // allocate Chuck_DL_Value * v = new Chuck_DL_Value; v->name = name; v->type = type; v->is_const = is_const; v->static_addr = addr; // add query->curr_class->svars.push_back( v ); query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_add_arg() // desc: add argument to function //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_arg( Chuck_DL_Query * query, const char * type, const char * name ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_arg invoked without begin_class..." ); return; } // make sure there is function if( !query->curr_func ) { // error EM_error2( 0, "class import: add_arg can only follow 'ctor', 'mfun', 'sfun', 'arg'..." ); return; } // allocate Chuck_DL_Value * v = new Chuck_DL_Value; v->name = name; v->type = type; // add query->curr_func->args.push_back( v ); } //----------------------------------------------------------------------------- // name: ck_add_ugen_func() // desc: (ugen only) add tick and pmsg functions //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_ugen_func( Chuck_DL_Query * query, f_tick ugen_tick, f_pmsg ugen_pmsg ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." ); return; } // make sure tick not defined already if( query->curr_class->ugen_tick && ugen_tick ) { // error EM_error2( 0, "class import: ugen_tick already defined..." ); return; } // make sure pmsg not defined already if( query->curr_class->ugen_pmsg && ugen_pmsg ) { // error EM_error2( 0, "class import: ugen_pmsg already defined..." ); return; } // set if( ugen_tick ) query->curr_class->ugen_tick = ugen_tick; if( ugen_pmsg ) query->curr_class->ugen_pmsg = ugen_pmsg; query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_add_ugen_ctrl() // desc: (ugen only) add ctrl parameters //----------------------------------------------------------------------------- void CK_DLL_CALL ck_add_ugen_ctrl( Chuck_DL_Query * query, f_ctrl ugen_ctrl, f_cget ugen_cget, const char * type, const char * name ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: add_ugen_func invoked without begin_class..." ); return; } // allocate Chuck_DL_Ctrl * c = new Chuck_DL_Ctrl; c->name = name; c->type = type; c->ctrl = ugen_ctrl; c->cget = ugen_cget; // set query->curr_func = NULL; } //----------------------------------------------------------------------------- // name: ck_end_class() // desc: end class/namespace, compile it //----------------------------------------------------------------------------- t_CKBOOL CK_DLL_CALL ck_end_class( Chuck_DL_Query * query ) { // make sure there is class if( !query->curr_class ) { // error EM_error2( 0, "class import: end_class invoked without begin_class..." ); return FALSE; } // type check the class? // pop assert( query->stack.size() ); query->curr_class = query->stack.back(); query->stack.pop_back(); return TRUE; } //------------------------------------------------------------------------------ // alternative functions to make stuff //------------------------------------------------------------------------------ Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun ) { return new Chuck_DL_Func( t, n, (t_CKUINT)mfun ); } Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun ) { return new Chuck_DL_Func( t, n, (t_CKUINT)sfun ); } Chuck_DL_Value * make_new_arg( const char * t, const char * n ) { return new Chuck_DL_Value( t, n ); } Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c ) { return new Chuck_DL_Value( t, n, c ); } Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a ) { return new Chuck_DL_Value( t, n, c, a ); } //----------------------------------------------------------------------------- // name: load() // desc: load dynamic link library //----------------------------------------------------------------------------- t_CKBOOL Chuck_DLL::load( const char * filename, const char * func, t_CKBOOL lazy ) { // open m_handle = dlopen( filename, lazy ? RTLD_LAZY : RTLD_NOW ); // still not there if( !m_handle ) { m_last_error = dlerror(); return FALSE; } // save the filename m_filename = filename; m_done_query = FALSE; m_func = func; // if not lazy, do it if( !lazy && !this->query() ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: load() // desc: load dynamic link library //----------------------------------------------------------------------------- t_CKBOOL Chuck_DLL::load( f_ck_query query_func, t_CKBOOL lazy ) { m_query_func = query_func; m_done_query = FALSE; m_func = "ck_query"; // if not lazy, do it if( !lazy && !this->query() ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: good() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_DLL::good() const { return ( m_handle != NULL || m_query_func != NULL ); } //----------------------------------------------------------------------------- // name: query() // desc: ... //----------------------------------------------------------------------------- const Chuck_DL_Query * Chuck_DLL::query( ) { if( !m_handle && !m_query_func ) { m_last_error = "dynamic link library not loaded for query..."; return NULL; } // return if there already if( m_done_query ) return &m_query; // get the address of the query function from the DLL if( !m_query_func ) m_query_func = (f_ck_query)this->get_addr( m_func.c_str() ); if( !m_query_func ) m_query_func = (f_ck_query)this->get_addr( (string("_")+m_func).c_str() ); if( !m_query_func ) { m_last_error = string("no query function found in dll '") + m_filename + string("'"); return NULL; } // get the address of the attach function from the DLL /* if( !m_attach_func ) m_attach_func = (f_ck_attach)this->get_addr( "ck_attach" ); if( !m_attach_func ) m_attach_func = (f_ck_attach)this->get_addr( "_ck_attach" ); // get the address of the detach function from the DLL if( !m_detach_func ) m_detach_func = (f_ck_detach)this->get_addr( "ck_detach" ); if( !m_detach_func ) m_detach_func = (f_ck_detach)this->get_addr( "_ck_detach" ); */ // do the query m_query.clear(); if( !m_query_func( &m_query ) ) { m_last_error = string("unsuccessful query in dll '") + m_filename + string("'"); return NULL; } // load the proto table /* Chuck_DL_Proto * proto; m_name2proto.clear(); for( t_CKUINT i = 0; i < m_query.dll_exports.size(); i++ ) { proto = &m_query.dll_exports[i]; if( m_name2proto[proto->name] ) { m_last_error = string("duplicate export name '") + proto->name + string("'"); return NULL; } // get the addr if( !proto->addr ) proto->addr = (f_ck_func)this->get_addr( (char *)proto->name.c_str() ); if( !proto->addr ) { m_last_error = string("no addr associated with export '") + proto->name + string("'"); return NULL; } // put in the lookup table m_name2proto[proto->name] = proto; } // load the proto table Chuck_UGen_Info * info; m_name2ugen.clear(); for( t_CKUINT j = 0; j < m_query.ugen_exports.size(); j++ ) { info = &m_query.ugen_exports[j]; if( m_name2ugen[info->name] ) { m_last_error = string("duplicate export ugen name '") + info->name + string("'"); return NULL; } // put in the lookup table m_name2ugen[info->name] = info; }*/ m_done_query = TRUE; // call attach // if( m_attach_func ) m_attach_func( 0, NULL ); return &m_query; } //----------------------------------------------------------------------------- // name: unload() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_DLL::unload() { if( !m_handle && !m_query_func ) { m_last_error = "cannot unload dynamic library - nothing open..."; return FALSE; } // if( m_detach_func ) m_detach_func( 0, NULL ); if( m_handle ) { dlclose( m_handle ); m_handle = NULL; } else m_query_func = NULL; return TRUE; } //----------------------------------------------------------------------------- // name: get_addr() // desc: ... //----------------------------------------------------------------------------- void * Chuck_DLL::get_addr( const char * symbol ) { if( !m_handle ) { m_last_error = "cannot find addr from dynamic library - nothing open..."; return FALSE; } return dlsym( m_handle, symbol ); } //----------------------------------------------------------------------------- // name: last_error() // desc: ... //----------------------------------------------------------------------------- const char * Chuck_DLL::last_error() const { return m_last_error.c_str(); } //----------------------------------------------------------------------------- // name: name() // desc: ... //----------------------------------------------------------------------------- const char * Chuck_DLL::name() const { return m_id.c_str(); } //----------------------------------------------------------------------------- // name: Chuck_DL_Query // desc: ... //----------------------------------------------------------------------------- Chuck_DL_Query::Chuck_DL_Query( ) { // set the pointers to functions so the module can call setname = ck_setname; begin_class = ck_begin_class; add_ctor = ck_add_ctor; add_dtor = ck_add_dtor; add_mfun = ck_add_mfun; add_sfun = ck_add_sfun; add_mvar = ck_add_mvar; add_svar = ck_add_svar; add_arg = ck_add_arg; add_ugen_func = ck_add_ugen_func; add_ugen_ctrl = ck_add_ugen_ctrl; end_class = ck_end_class; dll_name = "[noname]"; reserved = NULL; curr_class = NULL; curr_func = NULL; #ifndef __CKDL_NO_BBQ__ srate = Digitalio::sampling_rate() ; bufsize = Digitalio::buffer_size(); #else srate = 0; bufsize = 0; #endif linepos = 0; } //----------------------------------------------------------------------------- // name: clear() // desc: ... //----------------------------------------------------------------------------- void Chuck_DL_Query::clear() { // set to 0 dll_name = "[noname]"; // line pos linepos = 0; // delete classes for( t_CKUINT i = 0; i < classes.size(); i++ ) delete classes[i]; // clear classes.clear(); } //----------------------------------------------------------------------------- // name: ~Chuck_DL_Class() // desc: ... //----------------------------------------------------------------------------- Chuck_DL_Class::~Chuck_DL_Class() { t_CKUINT i; // delete mfuns for( i = 0; i < mfuns.size(); i++ ) delete mfuns[i]; // delete sfuns for( i = 0; i < sfuns.size(); i++ ) delete sfuns[i]; // delete mvars for( i = 0; i < mvars.size(); i++ ) delete mvars[i]; // delete svars for( i = 0; i < svars.size(); i++ ) delete svars[i]; // delete classes for( i = 0; i < classes.size(); i++ ) delete classes[i]; } //----------------------------------------------------------------------------- // name: ~Chuck_DL_Func() // desc: ... //----------------------------------------------------------------------------- Chuck_DL_Func::~Chuck_DL_Func() { for( t_CKUINT i = 0; i < args.size(); i++ ) delete args[i]; } // windows #if defined(__WINDOWS_DS__) extern "C" { #include void *dlopen( const char *path, int mode ) { return (void *)LoadLibrary(path); } int dlclose( void *handle ) { FreeLibrary((HMODULE)handle); return 1; } void *dlsym( void * handle, const char *symbol ) { return (void *)GetProcAddress((HMODULE)handle, symbol); } const char * dlerror( void ) { int error = GetLastError(); if( error == 0 ) return NULL; sprintf( dlerror_buffer, "%i", error ); return dlerror_buffer; } } #endif // mac os x #if defined(__MACOSX_CORE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1030 extern "C" { #include #include #include #include #include #include #include #include "mach-o/dyld.h" /* * debugging macros */ #if DEBUG > 0 #define DEBUG_PRINT(format) fprintf(stderr,(format));fflush(stderr) #define DEBUG_PRINT1(format,arg1) fprintf(stderr,(format),(arg1));\ fflush(stderr) #define DEBUG_PRINT2(format,arg1,arg2) fprintf(stderr,(format),\ (arg1),(arg2));fflush(stderr) #define DEBUG_PRINT3(format,arg1,arg2,arg3) fprintf(stderr,(format),\ (arg1),(arg2),(arg3));fflush(stderr) #else #define DEBUG_PRINT(format) /**/ #define DEBUG_PRINT1(format,arg1) /**/ #define DEBUG_PRINT2(format,arg1,arg2) /**/ #define DEBUG_PRINT3(format,arg1,arg2,arg3) /**/ #undef DEBUG #endif /* * The structure of a dlopen() handle. */ struct dlopen_handle { dev_t dev; /* the path's device and inode number from stat(2) */ ino_t ino; int dlopen_mode; /* current dlopen mode for this handle */ int dlopen_count; /* number of times dlopen() called on this handle */ NSModule module; /* the NSModule returned by NSLinkModule() */ struct dlopen_handle *prev; struct dlopen_handle *next; }; static struct dlopen_handle *dlopen_handles = NULL; static const struct dlopen_handle main_program_handle = {NULL}; static char *dlerror_pointer = NULL; /* * NSMakePrivateModulePublic() is not part of the public dyld API so we define * it here. The internal dyld function pointer for * __dyld_NSMakePrivateModulePublic is returned so thats all that maters to get * the functionality need to implement the dlopen() interfaces. */ static int NSMakePrivateModulePublic( NSModule module) { static int (*p)(NSModule module) = NULL; if(p == NULL) _dyld_func_lookup("__dyld_NSMakePrivateModulePublic", (unsigned long *)&p); if(p == NULL){ #ifdef DEBUG printf("_dyld_func_lookup of __dyld_NSMakePrivateModulePublic " "failed\n"); #endif return(FALSE); } return(p(module)); } /* * helper routine: search for a named module in various locations */ static int _dl_search_paths( const char *filename, char *pathbuf, struct stat *stat_buf) { const char *pathspec; const char *element; const char *p; char *q; char *pathbuf_end; const char *envvars[] = { "$DYLD_LIBRARY_PATH", "$LD_LIBRARY_PATH", "/usr/lib:/lib", NULL }; int envvar_index; pathbuf_end = pathbuf + PATH_MAX - 8; for(envvar_index = 0; envvars[envvar_index]; envvar_index++){ if(envvars[envvar_index][0] == '$'){ pathspec = getenv(envvars[envvar_index]+1); } else { pathspec = envvars[envvar_index]; } if(pathspec != NULL){ element = pathspec; while(*element){ /* extract path list element */ p = element; q = pathbuf; while(*p && *p != ':' && q < pathbuf_end) *q++ = *p++; if(q == pathbuf){ /* empty element */ if(*p){ element = p+1; continue; } break; } if (*p){ element = p+1; } else{ element = p; /* this terminates the loop */ } /* add slash if neccessary */ if(*(q-1) != '/' && q < pathbuf_end){ *q++ = '/'; } /* append module name */ p = filename; while(*p && q < pathbuf_end) *q++ = *p++; *q++ = 0; if(q >= pathbuf_end){ /* maybe add an error message here */ break; } if(stat(pathbuf, stat_buf) == 0){ return 0; } } } } /* we have searched everywhere, now we give up */ return -1; } /* * dlopen() the MacOS X version of the FreeBSD dlopen() interface. */ void * dlopen( const char *path, int mode) { const char *module_path; void *retval; struct stat stat_buf; NSObjectFileImage objectFileImage; NSObjectFileImageReturnCode ofile_result_code; NSModule module; struct dlopen_handle *p; unsigned long options; NSSymbol NSSymbol; void (*init)(void); char pathbuf[PATH_MAX]; DEBUG_PRINT2("libdl: dlopen(%s,0x%x) -> ", path, (unsigned int)mode); dlerror_pointer = NULL; /* * A NULL path is to indicate the caller wants a handle for the * main program. */ if(path == NULL){ retval = (void *)&main_program_handle; DEBUG_PRINT1("main / %p\n", retval); return(retval); } /* see if the path exists and if so get the device and inode number */ if(stat(path, &stat_buf) == -1){ dlerror_pointer = strerror(errno); if(path[0] == '/'){ DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer); return(NULL); } /* search for the module in various places */ if(_dl_search_paths(path, pathbuf, &stat_buf)){ /* dlerror_pointer is unmodified */ DEBUG_PRINT1("ERROR (stat): %s\n", dlerror_pointer); return(NULL); } DEBUG_PRINT1("found %s -> ", pathbuf); module_path = pathbuf; dlerror_pointer = NULL; } else{ module_path = path; } /* * If we don't want an unshared handle see if we already have a handle * for this path. */ if((mode & RTLD_UNSHARED) != RTLD_UNSHARED){ p = dlopen_handles; while(p != NULL){ if(p->dev == stat_buf.st_dev && p->ino == stat_buf.st_ino){ /* skip unshared handles */ if((p->dlopen_mode & RTLD_UNSHARED) == RTLD_UNSHARED) continue; /* * We have already created a handle for this path. The * caller might be trying to promote an RTLD_LOCAL handle * to a RTLD_GLOBAL. Or just looking it up with * RTLD_NOLOAD. */ if((p->dlopen_mode & RTLD_LOCAL) == RTLD_LOCAL && (mode & RTLD_GLOBAL) == RTLD_GLOBAL){ /* promote the handle */ if(NSMakePrivateModulePublic(p->module) == TRUE){ p->dlopen_mode &= ~RTLD_LOCAL; p->dlopen_mode |= RTLD_GLOBAL; p->dlopen_count++; DEBUG_PRINT1("%p\n", p); return(p); } else{ dlerror_pointer = "can't promote handle from " "RTLD_LOCAL to RTLD_GLOBAL"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } } p->dlopen_count++; DEBUG_PRINT1("%p\n", p); return(p); } p = p->next; } } /* * We do not have a handle for this path if we were just trying to * look it up return NULL to indicate we don't have it. */ if((mode & RTLD_NOLOAD) == RTLD_NOLOAD){ dlerror_pointer = "no existing handle for path RTLD_NOLOAD test"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } /* try to create an object file image from this path */ ofile_result_code = NSCreateObjectFileImageFromFile(module_path, &objectFileImage); if(ofile_result_code != NSObjectFileImageSuccess){ switch(ofile_result_code){ case NSObjectFileImageFailure: dlerror_pointer = "object file setup failure"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); case NSObjectFileImageInappropriateFile: dlerror_pointer = "not a Mach-O MH_BUNDLE file type"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); case NSObjectFileImageArch: dlerror_pointer = "no object for this architecture"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); case NSObjectFileImageFormat: dlerror_pointer = "bad object file format"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); case NSObjectFileImageAccess: dlerror_pointer = "can't read object file"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); default: dlerror_pointer = "unknown error from " "NSCreateObjectFileImageFromFile()"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } } /* try to link in this object file image */ options = NSLINKMODULE_OPTION_PRIVATE; if((mode & RTLD_NOW) == RTLD_NOW) options |= NSLINKMODULE_OPTION_BINDNOW; module = NSLinkModule(objectFileImage, module_path, options); NSDestroyObjectFileImage(objectFileImage) ; if(module == NULL){ dlerror_pointer = "NSLinkModule() failed for dlopen()"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } /* * If the handle is to be global promote the handle. It is done this * way to avoid multiply defined symbols. */ if((mode & RTLD_GLOBAL) == RTLD_GLOBAL){ if(NSMakePrivateModulePublic(module) == FALSE){ dlerror_pointer = "can't promote handle from RTLD_LOCAL to " "RTLD_GLOBAL"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } } p = (dlopen_handle *)malloc(sizeof(struct dlopen_handle)); if(p == NULL){ dlerror_pointer = "can't allocate memory for the dlopen handle"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } /* fill in the handle */ p->dev = stat_buf.st_dev; p->ino = stat_buf.st_ino; if(mode & RTLD_GLOBAL) p->dlopen_mode = RTLD_GLOBAL; else p->dlopen_mode = RTLD_LOCAL; p->dlopen_mode |= (mode & RTLD_UNSHARED) | (mode & RTLD_NODELETE) | (mode & RTLD_LAZY_UNDEF); p->dlopen_count = 1; p->module = module; p->prev = NULL; p->next = dlopen_handles; if(dlopen_handles != NULL) dlopen_handles->prev = p; dlopen_handles = p; /* call the init function if one exists */ NSSymbol = NSLookupSymbolInModule(p->module, "__init"); if(NSSymbol != NULL){ init = ( void(*)() )NSAddressOfSymbol(NSSymbol); init(); } DEBUG_PRINT1("%p\n", p); return(p); } /* * dlsym() the MacOS X version of the FreeBSD dlopen() interface. */ void * dlsym( void * handle, const char *symbol) { struct dlopen_handle *dlopen_handle, *p; NSSymbol NSSymbol; void *address; DEBUG_PRINT2("libdl: dlsym(%p,%s) -> ", handle, symbol); dlopen_handle = (struct dlopen_handle *)handle; /* * If this is the handle for the main program do a global lookup. */ if(dlopen_handle == (struct dlopen_handle *)&main_program_handle){ if(NSIsSymbolNameDefined(symbol) == TRUE){ NSSymbol = NSLookupAndBindSymbol(symbol); address = NSAddressOfSymbol(NSSymbol); dlerror_pointer = NULL; DEBUG_PRINT1("%p\n", address); return(address); } else{ dlerror_pointer = "symbol not found"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } } /* * Find this handle and do a lookup in just this module. */ p = dlopen_handles; while(p != NULL){ if(dlopen_handle == p){ NSSymbol = NSLookupSymbolInModule(p->module, symbol); if(NSSymbol != NULL){ address = NSAddressOfSymbol(NSSymbol); dlerror_pointer = NULL; DEBUG_PRINT1("%p\n", address); return(address); } else{ dlerror_pointer = "symbol not found"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } } p = p->next; } dlerror_pointer = "bad handle passed to dlsym()"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(NULL); } /* * dlerror() the MacOS X version of the FreeBSD dlopen() interface. */ const char * dlerror( void) { const char *p; p = (const char *)dlerror_pointer; dlerror_pointer = NULL; return(p); } /* * dlclose() the MacOS X version of the FreeBSD dlopen() interface. */ int dlclose( void * handle) { struct dlopen_handle *p, *q; unsigned long options; NSSymbol NSSymbol; void (*fini)(void); DEBUG_PRINT1("libdl: dlclose(%p) -> ", handle); dlerror_pointer = NULL; q = (struct dlopen_handle *)handle; p = dlopen_handles; while(p != NULL){ if(p == q){ /* if the dlopen() count is not zero we are done */ p->dlopen_count--; if(p->dlopen_count != 0){ DEBUG_PRINT("OK"); return(0); } /* call the fini function if one exists */ NSSymbol = NSLookupSymbolInModule(p->module, "__fini"); if(NSSymbol != NULL){ fini = ( void(*)() )NSAddressOfSymbol(NSSymbol); fini(); } /* unlink the module for this handle */ options = 0; if(p->dlopen_mode & RTLD_NODELETE) options |= NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED; if(p->dlopen_mode & RTLD_LAZY_UNDEF) options |= NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES; if(NSUnLinkModule(p->module, options) == FALSE){ dlerror_pointer = "NSUnLinkModule() failed for dlclose()"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(-1); } if(p->prev != NULL) p->prev->next = p->next; if(p->next != NULL) p->next->prev = p->prev; if(dlopen_handles == p) dlopen_handles = p->next; free(p); DEBUG_PRINT("OK"); return(0); } p = p->next; } dlerror_pointer = "invalid handle passed to dlclose()"; DEBUG_PRINT1("ERROR: %s\n", dlerror_pointer); return(-1); } } #else // do nothing, it's all in dlfcn #endif chuck-1.2.0.8.dfsg/src/chuck_dl.h0000644000175000017500000004711010600421722015056 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_dl.h // desc: chuck dynamic linking header // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ari Lazier (alazier@cs.princeton.edu) // mac os code based on apple's open source // // date: spring 2004 - 1.1 // spring 2005 - 1.2 //----------------------------------------------------------------------------- #ifndef __CHUCK_DL_H__ #define __CHUCK_DL_H__ #include "chuck_def.h" #include "chuck_oo.h" #include #include #include // forward references struct Chuck_DL_Query; struct Chuck_DL_Class; struct Chuck_DL_Func; struct Chuck_DL_Value; struct Chuck_DL_Ctrl; union Chuck_DL_Return; struct Chuck_DLL; struct Chuck_UGen; // param conversion - to extract values from ARGS to functions #define GET_CK_FLOAT(ptr) (*(t_CKFLOAT *)ptr) #define GET_CK_SINGLE(ptr) (*(float *)ptr) #define GET_CK_DOUBLE(ptr) (*(double *)ptr) #define GET_CK_INT(ptr) (*(t_CKINT *)ptr) #define GET_CK_UINT(ptr) (*(t_CKUINT *)ptr) #define GET_CK_TIME(ptr) (*(t_CKTIME *)ptr) #define GET_CK_DUR(ptr) (*(t_CKDUR *)ptr) #define GET_CK_OBJECT(ptr) (*(Chuck_Object **)ptr) #define GET_CK_STRING(ptr) (*(Chuck_String **)ptr) // param conversion with pointer advance #define GET_NEXT_FLOAT(ptr) (*((t_CKFLOAT *&)ptr)++) #define GET_NEXT_SINGLE(ptr) (*((float *&)ptr)++) #define GET_NEXT_DOUBLE(ptr) (*((double *&)ptr)++) #define GET_NEXT_INT(ptr) (*((t_CKINT *&)ptr)++) #define GET_NEXT_UINT(ptr) (*((t_CKUINT *&)ptr)++) #define GET_NEXT_TIME(ptr) (*((t_CKTIME *&)ptr)++) #define GET_NEXT_DUR(ptr) (*((t_CKDUR *&)ptr)++) #define GET_NEXT_OBJECT(ptr) (*((Chuck_Object **&)ptr)++) #define GET_NEXT_STRING(ptr) (*((Chuck_String **&)ptr)++) // param conversion #define SET_CK_FLOAT(ptr,v) (*(t_CKFLOAT *&)ptr=v) #define SET_CK_SINGLE(ptr,v) (*(float *&)ptr=v) #define SET_CK_DOUBLE(ptr,v) (*(double *&)ptr=v) #define SET_CK_INT(ptr,v) (*(t_CKINT *&)ptr=v) #define SET_CK_UINT(ptr,v) (*(t_CKUINT *&)ptr=v) #define SET_CK_TIME(ptr,v) (*(t_CKTIME *&)ptr=v) #define SET_CK_DUR(ptr,v) (*(t_CKDUR *&)ptr=v) #define SET_CK_STRING(ptr,v) (*(Chuck_String **&)ptr=v) // param conversion with pointer advance #define SET_NEXT_FLOAT(ptr,v) (*((t_CKFLOAT *&)ptr)++=v) #define SET_NEXT_SINGLE(ptr,v) (*((float *&)ptr)++=v) #define SET_NEXT_DOUBLE(ptr,v) (*((double *&)ptr)++=v) #define SET_NEXT_INT(ptr,v) (*((t_CKINT *&)ptr)++=v) #define SET_NEXT_UINT(ptr,v) (*((t_CKUINT *&)ptr)++=v) #define SET_NEXT_TIME(ptr,v) (*((t_CKTIME *&)ptr)++=v) #define SET_NEXT_DUR(ptr,v) (*((t_CKDUR *&)ptr)++=v) #define SET_NEXT_STRING(ptr,v) (*((Chuck_String **&)ptr)++=v) // param conversion - to extract values from object's data segment #define OBJ_MEMBER_DATA(obj,offset) (obj->data + offset) #define OBJ_MEMBER_FLOAT(obj,offset) (*(t_CKFLOAT *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_SINGLE(obj,offset) (*(float *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_DOUBLE(obj,offset) (*(double *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_INT(obj,offset) (*(t_CKINT *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_UINT(obj,offset) (*(t_CKUINT *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_TIME(obj,offset) (*(t_CKTIME *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_DUR(obj,offset) (*(t_CKDUR *)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_OBJECT(obj,offset) (*(Chuck_Object **)OBJ_MEMBER_DATA(obj,offset)) #define OBJ_MEMBER_STRING(obj,offset) (*(Chuck_String **)OBJ_MEMBER_DATA(obj,offset)) // chuck dll export linkage and calling convention #if defined (__PLATFORM_WIN32__) #define CK_DLL_LINKAGE extern "C" __declspec( dllexport ) #else #define CK_DLL_LINKAGE extern "C" #endif // calling convention of functions provided by chuck to the dll #if defined(__WINDOWS_DS__) #define CK_DLL_CALL _cdecl #else #define CK_DLL_CALL #endif // macro for defining ChucK DLL export functions // example: CK_DLL_EXPORT(int) foo() { return 1; } #define CK_DLL_EXPORT(type) CK_DLL_LINKAGE type CK_DLL_CALL // macro for defining ChucK DLL export query-functions // example: CK_DLL_QUERY #define CK_DLL_QUERY CK_DLL_EXPORT(t_CKBOOL) ck_query( Chuck_DL_Query * QUERY ) // macro for defining ChucK DLL export constructors // example: CK_DLL_CTOR(foo) #define CK_DLL_CTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export destructors // example: CK_DLL_DTOR(foo) #define CK_DLL_DTOR(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export member functions // example: CK_DLL_MFUN(foo) #define CK_DLL_MFUN(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export static functions // example: CK_DLL_SFUN(foo) #define CK_DLL_SFUN(name) CK_DLL_EXPORT(void) name( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export ugen tick functions // example: CK_DLL_TICK(foo) #define CK_DLL_TICK(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export ugen ctrl functions // example: CK_DLL_CTRL(foo) #define CK_DLL_CTRL(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export ugen cget functions // example: CK_DLL_CGET(foo) #define CK_DLL_CGET(name) CK_DLL_EXPORT(void) name( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ) // macro for defining ChucK DLL export ugen pmsg functions // example: CK_DLL_PMSG(foo) #define CK_DLL_PMSG(name) CK_DLL_EXPORT(t_CKBOOL) name( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED ) // macros for DLL exports // example: DLL_QUERY query( Chuck_DL_Query * QUERY ) // example: DLL_FUNC foo( void * ARGS, Chuck_DL_Return * RETURN ) // example: DLL_UGEN_F foo_tick( Chuck_UGen * SELF, SAMPLE, SAMPLE * out ); #define DLL_QUERY CK_DLL_EXPORT(t_CKBOOL) #define DLL_FUNC CK_DLL_EXPORT(void) #define UGEN_CTOR CK_DLL_EXPORT(void *) #define UGEN_DTOR CK_DLL_EXPORT(void) #define UGEN_TICK CK_DLL_EXPORT(t_CKBOOL) #define UGEN_PMSG CK_DLL_EXPORT(t_CKBOOL) #define UGEN_CTRL CK_DLL_EXPORT(t_CKVOID) #define UGEN_CGET CK_DLL_EXPORT(t_CKVOID) //----------------------------------------------------------------------------- // dynamic linking class interface prototypes //----------------------------------------------------------------------------- extern "C" { // query typedef t_CKBOOL (CK_DLL_CALL * f_ck_query)( Chuck_DL_Query * QUERY ); // object typedef t_CKVOID (CK_DLL_CALL * f_ctor)( Chuck_Object * SELF, void * ARGS, Chuck_VM_Shred * SHRED ); typedef t_CKVOID (CK_DLL_CALL * f_dtor)( Chuck_Object * SELF, Chuck_VM_Shred * SHRED ); typedef t_CKVOID (CK_DLL_CALL * f_mfun)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ); typedef t_CKVOID (CK_DLL_CALL * f_sfun)( void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ); // ugen specific typedef t_CKBOOL (CK_DLL_CALL * f_tick)( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED ); typedef t_CKVOID (CK_DLL_CALL * f_ctrl)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ); typedef t_CKVOID (CK_DLL_CALL * f_cget)( Chuck_Object * SELF, void * ARGS, Chuck_DL_Return * RETURN, Chuck_VM_Shred * SHRED ); typedef t_CKBOOL (CK_DLL_CALL * f_pmsg)( Chuck_Object * SELF, const char * MSG, void * ARGS, Chuck_VM_Shred * SHRED ); } // default name in DLL/ckx to look for #define CK_QUERY_FUNC "ck_query" // bad object data offset #define CK_INVALID_OFFSET 0xffffffff //----------------------------------------------------------------------------- // chuck DLL query functions, implemented on chuck side for portability //----------------------------------------------------------------------------- extern "C" { // set name of ckx typedef void ( CK_DLL_CALL * f_setname)( Chuck_DL_Query * query, const char * name ); // begin class/namespace, can be nested typedef void (CK_DLL_CALL * f_begin_class)( Chuck_DL_Query * query, const char * name, const char * parent ); // add constructor, must be betwen begin/end_class : use f_add_arg to add arguments immediately after typedef void (CK_DLL_CALL * f_add_ctor)( Chuck_DL_Query * query, f_ctor ctor ); // add destructor - cannot have args typedef void (CK_DLL_CALL * f_add_dtor)( Chuck_DL_Query * query, f_dtor dtor ); // add member function - args to follow typedef void (CK_DLL_CALL * f_add_mfun)( Chuck_DL_Query * query, f_mfun mfun, const char * type, const char * name ); // add static function - args to follow typedef void (CK_DLL_CALL * f_add_sfun)( Chuck_DL_Query * query, f_sfun sfun, const char * type, const char * name ); // add member variable typedef void (CK_DLL_CALL * f_add_mvar)( Chuck_DL_Query * query, const char * type, const char * name, t_CKBOOL is_const ); // TODO: public/protected/private // add static variable typedef void (CK_DLL_CALL * f_add_svar)( Chuck_DL_Query * query, const char * type, const char * name, t_CKBOOL is_const, void * static_addr ); // TODO: public/protected/private // add arg - follows ctor mfun sfun typedef void (CK_DLL_CALL * f_add_arg)( Chuck_DL_Query * query, const char * type, const char * name ); // ** functions for adding unit generators, must extend ugen typedef void (CK_DLL_CALL * f_add_ugen_func)( Chuck_DL_Query * query, f_tick tick, f_pmsg pmsg ); // ** add a ugen control typedef void (CK_DLL_CALL * f_add_ugen_ctrl)( Chuck_DL_Query * query, f_ctrl ctrl, f_cget cget, const char * type, const char * name ); // end class/namespace - must correspondent with begin_class. returns false on error typedef t_CKBOOL (CK_DLL_CALL * f_end_class)( Chuck_DL_Query * query ); } //----------------------------------------------------------------------------- // name: struct Chuck_DL_Query // desc: passed to module //----------------------------------------------------------------------------- struct Chuck_DL_Query { // function pointers - to be called from client module // QUERY->setname( QUERY, ... ); // // set the name of the module f_setname setname; // begin class/namespace, can be nexted f_begin_class begin_class; // add constructor, can be followed by add_arg f_add_ctor add_ctor; // add destructor, no args allowed f_add_dtor add_dtor; // add member function, can be followed by add_arg f_add_mfun add_mfun; // add static function, can be followed by add_arg f_add_sfun add_sfun; // add member variable f_add_mvar add_mvar; // add static variable f_add_svar add_svar; // add argument to function f_add_arg add_arg; // (ugen only) add tick and pmsg functions f_add_ugen_func add_ugen_func; // (ugen only) add ctrl parameters f_add_ugen_ctrl add_ugen_ctrl; // end class/namespace, compile it f_end_class end_class; // name std::string name; // current class Chuck_DL_Class * curr_class; // current function Chuck_DL_Func * curr_func; // collection of class std::vector classes; // stack std::vectorstack; // name of dll std::string dll_name; // dll Chuck_DLL * dll_ref; // reserved void * reserved; // sample rate t_CKUINT srate; // bsize t_CKUINT bufsize; // line pos int linepos; // constructor Chuck_DL_Query(); // desctructor ~Chuck_DL_Query() { this->clear(); } // clear void clear(); }; //----------------------------------------------------------------------------- // name: struct Chuck_DL_Class // desc: class built from module //----------------------------------------------------------------------------- struct Chuck_DL_Class { // the name of the class std::string name; // the name of the parent std::string parent; // ctor std::vector ctors; // dtor Chuck_DL_Func * dtor; // mfun std::vector mfuns; // sfun std::vector sfuns; // mdata std::vector mvars; // sdata std::vector svars; // ugen_tick f_tick ugen_tick; // ugen_pmsg f_pmsg ugen_pmsg; // ugen_ctrl/cget std::vector ugen_ctrl; // collection of recursive classes std::vector classes; // constructor Chuck_DL_Class() { dtor = NULL; ugen_tick = NULL; ugen_pmsg = NULL; } // destructor ~Chuck_DL_Class(); }; //----------------------------------------------------------------------------- // name: struct Chuck_DL_Value // desc: value from module //----------------------------------------------------------------------------- struct Chuck_DL_Value { // the name of the value std::string name; // the type of the value std::string type; // is const t_CKBOOL is_const; // addr static void * static_addr; // constructor Chuck_DL_Value() { is_const = FALSE; static_addr = NULL; } Chuck_DL_Value( const char * t, const char * n, t_CKBOOL c = FALSE, void * a = NULL ) { name = n; type = t; is_const = c; static_addr = a; } }; //----------------------------------------------------------------------------- // name: struct Chuck_DL_Func // desc: function from module //----------------------------------------------------------------------------- struct Chuck_DL_Func { // the name of the function std::string name; // the return type std::string type; // the pointer union { f_ctor ctor; f_dtor dtor; f_mfun mfun; f_sfun sfun; t_CKUINT addr; }; // arguments std::vector args; // constructor Chuck_DL_Func() { ctor = NULL; } Chuck_DL_Func( const char * t, const char * n, t_CKUINT a ) { name = n; type = t; addr = a; } // destructor ~Chuck_DL_Func(); // add arg void add_arg( const char * t, const char * n ) { args.push_back( new Chuck_DL_Value( t, n ) ); } }; //----------------------------------------------------------------------------- // name: struct Chuck_DL_Ctrl // desc: ctrl for ugen //----------------------------------------------------------------------------- struct Chuck_DL_Ctrl { // the name of the ctrl std::string name; // the first type std::string type; // the types of the value std::vector types; // ctrl f_ctrl ctrl; // cget f_cget cget; }; //------------------------------------------------------------------------------ // alternative functions to make stuff //------------------------------------------------------------------------------ Chuck_DL_Func * make_new_mfun( const char * t, const char * n, f_mfun mfun ); Chuck_DL_Func * make_new_sfun( const char * t, const char * n, f_sfun sfun ); Chuck_DL_Value * make_new_arg( const char * t, const char * n ); Chuck_DL_Value * make_new_mvar( const char * t, const char * n, t_CKBOOL c = FALSE ); Chuck_DL_Value * make_new_svar( const char * t, const char * n, t_CKBOOL c, void * a ); //------------------------------------------------------------------------------ // name: union Chuck_DL_Return // desc: dynamic link return function return struct //------------------------------------------------------------------------------ union Chuck_DL_Return { t_CKINT v_int; t_CKUINT v_uint; t_CKFLOAT v_float; t_CKDUR v_dur; t_CKTIME v_time; Chuck_Object * v_object; Chuck_String * v_string; Chuck_DL_Return() { v_float = 0.0; } }; //----------------------------------------------------------------------------- // name: struct Chuck_DLL // desc: dynamic link library //----------------------------------------------------------------------------- struct Chuck_DLL : public Chuck_VM_Object { public: // load dynamic ckx/dll from filename t_CKBOOL load( const char * filename, const char * func = CK_QUERY_FUNC, t_CKBOOL lazy = FALSE ); t_CKBOOL load( f_ck_query query_func, t_CKBOOL lazy = FALSE ); // get address in loaded ckx void * get_addr( const char * symbol ); // get last error const char * last_error() const; // unload the ckx t_CKBOOL unload( ); // query the content of the dll const Chuck_DL_Query * query( ); // is good t_CKBOOL good() const; // name const char * name() const; public: // constructor Chuck_DLL( const char * xid = NULL ) : m_handle(NULL), m_id(xid ? xid : ""), m_done_query(FALSE), m_query_func(NULL) { } // destructor ~Chuck_DLL() { this->unload(); } protected: // data void * m_handle; std::string m_last_error; std::string m_filename; std::string m_id; std::string m_func; t_CKBOOL m_done_query; f_ck_query m_query_func; Chuck_DL_Query m_query; }; // dlfcn interface #if defined(__MACOSX_CORE__) #include #endif // dlfcn interface, panther or below #if defined(__MACOSX_CORE__) && MAC_OS_X_VERSION_MAX_ALLOWED <= 1030 #ifdef __cplusplus extern "C" { #endif void * dlopen( const char * path, int mode ); void * dlsym( void * handle, const char * symbol ); const char * dlerror( void ); int dlclose( void * handle ); #define RTLD_LAZY 0x1 #define RTLD_NOW 0x2 #define RTLD_LOCAL 0x4 #define RTLD_GLOBAL 0x8 #define RTLD_NOLOAD 0x10 #define RTLD_SHARED 0x20 /* not used, the default */ #define RTLD_UNSHARED 0x40 #define RTLD_NODELETE 0x80 #define RTLD_LAZY_UNDEF 0x100 #ifdef __cplusplus } #endif #elif defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) #ifdef __cplusplus extern "C" { #endif #define RTLD_LAZY 0x1 #define RTLD_NOW 0x2 #define RTLD_LOCAL 0x4 #define RTLD_GLOBAL 0x8 #define RTLD_NOLOAD 0x10 #define RTLD_SHARED 0x20 /* not used, the default */ #define RTLD_UNSHARED 0x40 #define RTLD_NODELETE 0x80 #define RTLD_LAZY_UNDEF 0x100 void * dlopen( const char * path, int mode ); void * dlsym( void * handle, const char * symbol ); const char * dlerror( void ); int dlclose( void * handle ); static char dlerror_buffer[128]; #ifdef __cplusplus } #endif #else #include "dlfcn.h" #endif #endif chuck-1.2.0.8.dfsg/src/chuck_emit.cpp0000644000175000017500000034130410600421722015752 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_emit.cpp // desc: chuck instruction emitter // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 // Autumn 2003 - updated // Autumn 2004 - redesign //----------------------------------------------------------------------------- #include "chuck_emit.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "chuck_instr.h" using namespace std; //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ); t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop = TRUE ); t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt ); t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt ); t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt ); t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt ); t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt ); t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt ); t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br ); t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont ); t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt ); t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt ); t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp ); t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ); t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary ); t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ); t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast ); t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix ); t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur ); t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array ); t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func, Chuck_Type * type, int linepos, t_CKBOOL spork = FALSE ); t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call, t_CKBOOL spork = FALSE ); t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call ); t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member ); t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if ); t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp ); t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array ); t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def ); t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def ); t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type ); t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, a_Array_Sub array, t_CKBOOL is_ref ); t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ); t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from ); t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, int linepos ); //----------------------------------------------------------------------------- // name: emit_engine_init() // desc: ... //----------------------------------------------------------------------------- Chuck_Emitter * emit_engine_init( Chuck_Env * env ) { // log EM_log( CK_LOG_SEVERE, "initializing emitter..." ); // TODO: ensure this in a better way assert( sizeof(t_CKUINT) == sizeof(void *) ); // allocate new emit Chuck_Emitter * emit = new Chuck_Emitter; // set the reference emit->env = env; return emit; } //----------------------------------------------------------------------------- // name: emit_engine_shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ) { if( !emit ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down emitter..." ); // delete delete emit; emit = NULL; return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_prog() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, te_HowMuch how_much ) { // make sure the code is NULL assert( emit->code == NULL ); // make sure the stack is empty assert( emit->stack.size() == 0 ); // make sure there is a context to emit assert( emit->env->context != NULL ); // make sure no code assert( emit->env->context->nspc->pre_ctor == NULL ); // log EM_log( CK_LOG_FINER, "(pass 4) emitting VM code '%s'...", emit->env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // return t_CKBOOL ret = TRUE; // allocate the code emit->code = new Chuck_Code; // set the current context emit->context = emit->env->context; // set the namespace emit->nspc = emit->context->nspc; // reset the func emit->func = NULL; // clear the code stack emit->stack.clear(); // name the code // emit->code->name = "(main)"; // whether code need this emit->code->need_this = TRUE; // loop over the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // code section // if only classes, then skip if( how_much == te_do_classes_only ) break; // emit statement list ret = emit_engine_emit_stmt_list( emit, prog->section->stmt_list ); break; case ae_section_func: // function definition // if only classes, then skip if( how_much == te_do_classes_only ) break; // check function definition ret = emit_engine_emit_func_def( emit, prog->section->func_def ); break; case ae_section_class: // class definition // if no classes, then skip if( how_much == te_do_no_classes ) break; // check class definition ret = emit_engine_emit_class_def( emit, prog->section->class_def ); break; default: // bad EM_error2( 0, "internal compiler error: unrecognized program section..." ); ret = FALSE; break; } // the next prog = prog->next; } if( ret ) { // append end of code emit->append( new Chuck_Instr_EOC ); // make sure assert( emit->context->nspc->pre_ctor == NULL ); // converted to virtual machine code emit->context->nspc->pre_ctor = emit_to_code( emit->code, NULL, emit->dump ); // add reference emit->context->nspc->pre_ctor->add_ref(); } // clear the code delete emit->code; emit->code = NULL; // pop indent EM_poplog(); // return the code return emit->context->nspc->pre_ctor; } //----------------------------------------------------------------------------- // name: emit_to_code() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code * emit_to_code( Chuck_Code * in, Chuck_VM_Code * out, t_CKBOOL dump ) { // log EM_log( CK_LOG_FINER, "emitting code: %d VM instructions...", in->code.size() ); // allocate the vm code Chuck_VM_Code * code = out ? out : new Chuck_VM_Code; // make sure assert( code->num_instr == 0 ); // size code->num_instr = in->code.size(); // allocate instruction pointers+ code->instr = new Chuck_Instr *[code->num_instr]; // set the stack depth code->stack_depth = in->stack_depth; // set whether code need this base pointer code->need_this = in->need_this; // set name code->name = in->name; // copy for( t_CKUINT i = 0; i < code->num_instr; i++ ) code->instr[i] = in->code[i]; // dump if( dump ) { // name of what we are dumping EM_error2( 0, "dumping %s:", in->name.c_str() ); // uh EM_error2( 0, "-------" ); for( t_CKUINT i = 0; i < code->num_instr; i++ ) EM_error2( 0, "[%i] %s( %s )", i, code->instr[i]->name(), code->instr[i]->params() ); EM_error2( 0, "-------\n" ); } return code; } //----------------------------------------------------------------------------- // name: // desc: ... //----------------------------------------------------------------------------- // t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); //----------------------------------------------------------------------------- // name: // desc: ... //----------------------------------------------------------------------------- // t_CKBOOL emit_engine_resolve( ); //----------------------------------------------------------------------------- // name: emit_engine_emit_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt_list( Chuck_Emitter * emit, a_Stmt_List list ) { t_CKBOOL ret = TRUE; // emit->push(); while( list && ret ) { ret = emit_engine_emit_stmt( emit, list->stmt ); list = list->next; } // emit->pop(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_stmt() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_stmt( Chuck_Emitter * emit, a_Stmt stmt, t_CKBOOL pop ) { // empty stmt list if( !stmt ) return TRUE; // return t_CKBOOL ret = TRUE; // loop over statements switch( stmt->s_type ) { case ae_stmt_exp: // expression statement // emit it ret = emit_engine_emit_exp( emit, stmt->stmt_exp ); if( !ret ) return FALSE; // need to pop the final value from stack if( ret && pop && stmt->stmt_exp->type->size > 0 ) { // sanity assert( stmt->stmt_exp->cast_to == NULL ); // exp a_Exp exp = stmt->stmt_exp; // hack if( exp->s_type == ae_exp_primary && exp->primary.s_type == ae_primary_hack ) exp = exp->primary.exp; // HACK! while( exp ) { // if decl, then expect only one word per var if( exp->s_type == ae_exp_decl ) emit->append( new Chuck_Instr_Reg_Pop_Word3( exp->decl.num_var_decls ) ); else if( exp->type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Pop_Word ); else if( exp->type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Pop_Word2 ); else { EM_error2( exp->linepos, "(emit): internal error: %i byte stack item unhandled...", exp->type->size ); return FALSE; } // go exp = exp->next; } } break; case ae_stmt_if: // if statement ret = emit_engine_emit_if( emit, &stmt->stmt_if ); break; case ae_stmt_for: // for statement ret = emit_engine_emit_for( emit, &stmt->stmt_for ); break; case ae_stmt_while: // while statement if( stmt->stmt_while.is_do ) ret = emit_engine_emit_do_while( emit, &stmt->stmt_while ); else ret = emit_engine_emit_while( emit, &stmt->stmt_while ); break; case ae_stmt_until: // until statement if( stmt->stmt_until.is_do ) ret = emit_engine_emit_do_until( emit, &stmt->stmt_until ); else ret = emit_engine_emit_until( emit, &stmt->stmt_until ); break; case ae_stmt_loop: // loop statement ret = emit_engine_emit_loop( emit, &stmt->stmt_loop ); break; case ae_stmt_switch: // switch statement // not implemented ret = FALSE; break; case ae_stmt_break: // break statement ret = emit_engine_emit_break( emit, &stmt->stmt_break ); break; case ae_stmt_code: // code segment ret = emit_engine_emit_code_segment( emit, &stmt->stmt_code ); break; case ae_stmt_continue: // continue statement ret = emit_engine_emit_continue( emit, &stmt->stmt_continue ); break; case ae_stmt_return: // return statement ret = emit_engine_emit_return( emit, &stmt->stmt_return ); break; case ae_stmt_case: // case statement // not implemented ret = FALSE; // ret = emit_engine_emit_case( emit, &stmt->stmt_case ); break; case ae_stmt_gotolabel: // goto label statement // not implemented ret = FALSE; // ret = emit_engine_emit_gotolabel( emit, &stmt->stmt_case ); break; default: // bad EM_error2( stmt->linepos, "(emit): internal error: unhandled statement type '%i'...", stmt->s_type ); break; } return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_if( Chuck_Emitter * emit, a_Stmt_If stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL; // push the stack, allowing for new local variables emit->push_scope(); // emit the condition ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // type of the condition switch( stmt->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Eq_double( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in if condition", stmt->cond->type->name.c_str() ); return FALSE; } if( !ret ) return FALSE; // append the op emit->append( op ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->if_body ); if( !ret ) return FALSE; // emit the skip to the end emit->append( op2 = new Chuck_Instr_Goto(0) ); // set the op's target op->set( emit->next_index() ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->else_body ); if( !ret ) return FALSE; // pop stack emit->pop_scope(); // set the op2's target op2->set( emit->next_index() ); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_for() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_for( Chuck_Emitter * emit, a_Stmt_For stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; // push the stack emit->push_scope(); // emit the cond ret = emit_engine_emit_stmt( emit, stmt->c1 ); if( !ret ) return FALSE; // the start index t_CKUINT start_index = emit->next_index(); t_CKUINT cont_index = 0; // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // emit the cond - keep the result on the stack emit_engine_emit_stmt( emit, stmt->c2, FALSE ); // could be NULL if( stmt->c2 ) { switch( stmt->c2->stmt_exp->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Eq_double( 0 ); break; default: EM_error2( stmt->c2->stmt_exp->linepos, "(emit): internal error: unhandled type '%s' in for conditional", stmt->c2->stmt_exp->type->name.c_str() ); return FALSE; } // append the op emit->append( op ); } // emit the body ret = emit_engine_emit_stmt( emit, stmt->body ); if( !ret ) return FALSE; // continue here cont_index = emit->next_index(); // emit the action if( stmt->c3 ) { ret = emit_engine_emit_exp( emit, stmt->c3 ); if( !ret ) return FALSE; // HACK! if( stmt->c3->type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Pop_Word2 ); else if( stmt->c3->type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Pop_Word ); else if( stmt->c3->type->size != 0 ) { EM_error2( stmt->c3->linepos, "(emit): internal error: non-void type size %i unhandled...", stmt->c3->type->size ); return FALSE; } } // go back to do check the condition emit->append( new Chuck_Instr_Goto( start_index ) ); // could be NULL if( stmt->c2 ) // set the op's target op->set( emit->next_index() ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( cont_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_while() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_while( Chuck_Emitter * emit, a_Stmt_While stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; // push stack emit->push_scope(); // get the index t_CKUINT start_index = emit->next_index(); // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // emit the cond ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // the condition switch( stmt->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Eq_double( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in while conditional", stmt->cond->type->name.c_str() ); return FALSE; } // append the op emit->append( op ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->body ); if( !ret ) return FALSE; // go back to do check the condition emit->append( new Chuck_Instr_Goto( start_index ) ); // set the op's target op->set( emit->next_index() ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( start_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_do_while() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_do_while( Chuck_Emitter * emit, a_Stmt_While stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; t_CKUINT start_index = emit->next_index(); // push stack emit->push_scope(); // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->body ); if( !ret ) return FALSE; // emit the cond ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // the condition switch( stmt->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Neq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Neq_double( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in do/while conditional", stmt->cond->type->c_name() ); return FALSE; } // append the op emit->append( op ); // set the op's target op->set( start_index ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( start_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_until() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_until( Chuck_Emitter * emit, a_Stmt_Until stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; // push stack emit->push_scope(); // get index t_CKUINT start_index = emit->next_index(); // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // emit the cond ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // condition switch( stmt->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Neq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Neq_double( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in until conditional", stmt->cond->type->name.c_str() ); return FALSE; } // append the op emit->append( op ); // emit the body emit_engine_emit_stmt( emit, stmt->body ); // go back to do check the condition emit->append( new Chuck_Instr_Goto( start_index ) ); // set the op's target op->set( emit->next_index() ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( start_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_do_until() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_do_until( Chuck_Emitter * emit, a_Stmt_Until stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; // push stack emit->push_scope(); // the index t_CKUINT start_index = emit->next_index(); // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->body ); if( !ret ) return FALSE; // emit the cond ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // condition switch( stmt->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Eq_double( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in do/until conditional", stmt->cond->type->name.c_str() ); return FALSE; } // append the op emit->append( op ); // set the op's target op->set( start_index ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( start_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_loop() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_loop( Chuck_Emitter * emit, a_Stmt_Loop stmt ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL; // TODO: SAFE_DELETE( counter ) t_CKINT * counter = NULL; // push stack emit->push_scope(); // emit the cond ret = emit_engine_emit_exp( emit, stmt->cond ); if( !ret ) return FALSE; // initialize our loop counter emit->append( new Chuck_Instr_Init_Loop_Counter( (t_CKUINT)(counter = new t_CKINT) ) ); // get the index t_CKUINT start_index = emit->next_index(); // mark the stack of continue emit->code->stack_cont.push_back( NULL ); // mark the stack of break emit->code->stack_break.push_back( NULL ); // push the value of the loop counter // TODO: get rid of hard code 4 emit->append( new Chuck_Instr_Reg_Push_Deref( (t_CKUINT)counter, 4 ) ); // ISSUE: 64-bit // get the type, taking cast into account Chuck_Type * type = stmt->cond->cast_to ? stmt->cond->cast_to : stmt->cond->type; // the condition switch( type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; default: EM_error2( stmt->cond->linepos, "(emit): internal error: unhandled type '%s' in while conditional", type->name.c_str() ); return FALSE; } // append the op emit->append( op ); // decrement the counter emit->append( new Chuck_Instr_Dec_int_Addr( (t_CKUINT)counter ) ); // emit the body ret = emit_engine_emit_stmt( emit, stmt->body ); if( !ret ) return FALSE; // go back to do check the condition emit->append( new Chuck_Instr_Goto( start_index ) ); // set the op's target op->set( emit->next_index() ); // stack of continue while( emit->code->stack_cont.size() && emit->code->stack_cont.back() ) { emit->code->stack_cont.back()->set( start_index ); emit->code->stack_cont.pop_back(); } // stack of break while( emit->code->stack_break.size() && emit->code->stack_break.back() ) { emit->code->stack_break.back()->set( emit->next_index() ); emit->code->stack_break.pop_back(); } // pop stack emit->pop_scope(); // pop continue stack emit->code->stack_cont.pop_back(); // pop break stack emit->code->stack_break.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_break() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_break( Chuck_Emitter * emit, a_Stmt_Break br ) { // append Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 ); emit->append( op ); // remember emit->code->stack_break.push_back( op ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_continue() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_continue( Chuck_Emitter * emit, a_Stmt_Continue cont ) { // append Chuck_Instr_Goto * op = new Chuck_Instr_Goto( 0 ); emit->append( op ); // remember emit->code->stack_cont.push_back( op ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_return() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_return( Chuck_Emitter * emit, a_Stmt_Return stmt ) { if( !emit_engine_emit_exp( emit, stmt->val ) ) return FALSE; // emit return // emit->append( new Chuck_Instr_Func_Return ); // determine where later Chuck_Instr_Goto * instr = new Chuck_Instr_Goto( 0 ); emit->append( instr ); emit->code->stack_return.push_back( instr ); return TRUE; } //----------------------------------------------------------------------------- // name: // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_switch( Chuck_Emitter * emit, a_Stmt_Switch stmt ); //----------------------------------------------------------------------------- // name: emit_engine_emit_exp() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp( Chuck_Emitter * emit, a_Exp exp ) { // for now... // assert( exp->next == NULL ); // loop over while( exp ) { switch( exp->s_type ) { case ae_exp_binary: if( !emit_engine_emit_exp_binary( emit, &exp->binary ) ) return FALSE; break; case ae_exp_unary: if( !emit_engine_emit_exp_unary( emit, &exp->unary ) ) return FALSE; break; case ae_exp_cast: if( !emit_engine_emit_exp_cast( emit, &exp->cast ) ) return FALSE; break; case ae_exp_postfix: if( !emit_engine_emit_exp_postfix( emit, &exp->postfix ) ) return FALSE; break; case ae_exp_dur: if( !emit_engine_emit_exp_dur( emit, &exp->dur ) ) return FALSE; break; case ae_exp_primary: if( !emit_engine_emit_exp_primary( emit, &exp->primary ) ) return FALSE; break; case ae_exp_array: if( !emit_engine_emit_exp_array( emit, &exp->array ) ) return FALSE; break; case ae_exp_func_call: if( !emit_engine_emit_exp_func_call( emit, &exp->func_call ) ) return FALSE; break; case ae_exp_dot_member: if( !emit_engine_emit_exp_dot_member( emit, &exp->dot_member ) ) return FALSE; break; case ae_exp_if: if( !emit_engine_emit_exp_if( emit, &exp->exp_if ) ) return FALSE; break; case ae_exp_decl: if( !emit_engine_emit_exp_decl( emit, &exp->decl, FALSE ) ) return FALSE; break; //case ae_exp_namespace: // if( !emit_engine_emit_exp_namespace( emit, &exp->name_space ) ) // return FALSE; // break; default: EM_error2( exp->linepos, "(emit): internal error: unhandled expression type '%i'...", exp->s_type ); return FALSE; } // implicit cast if( exp->cast_to != NULL ) if( !emit_engine_emit_cast( emit, exp->cast_to, exp->type ) ) return FALSE; exp = exp->next; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_binary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_binary( Chuck_Emitter * emit, a_Exp_Binary binary ) { // sanity assert( binary->self->emit_var == FALSE ); t_CKBOOL left = FALSE; t_CKBOOL right = FALSE; // hack to allow && to terminate as soon as possible - spencer // i.e. in ( 0 && f() ) the function f() will not be called // (obviates need for boolean AND instruction) if( binary->op == ae_op_and ) { Chuck_Instr_Branch_Op * op; // push default result emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); left = emit_engine_emit_exp( emit, binary->lhs ); if( !left ) return FALSE; // compare to 0; use default result if zero emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); emit->append( op = new Chuck_Instr_Branch_Eq_int( 0 ) ); // pop default result emit->append( new Chuck_Instr_Reg_Pop_Word ); // result of whole expression is now result of rhs right = emit_engine_emit_exp( emit, binary->rhs ); if( !right ) return FALSE; // set branch location op->set( emit->next_index() ); return TRUE; } // hack to allow || to terminate as soon as possible - spencer // i.e. in ( 1 || f() ) the function f() will not be called // (obviates need for boolean OR instruction) else if( binary->op == ae_op_or ) { Chuck_Instr_Branch_Op * op; // push default result emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) ); left = emit_engine_emit_exp( emit, binary->lhs ); if( !left ) return FALSE; // compare to 0; use default result if non-zero emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); emit->append( op = new Chuck_Instr_Branch_Neq_int( 0 ) ); // pop default result emit->append( new Chuck_Instr_Reg_Pop_Word ); // result of whole expression is now result of rhs right = emit_engine_emit_exp( emit, binary->rhs ); if( !right ) return FALSE; // set branch location op->set( emit->next_index() ); return TRUE; } // emit left = emit_engine_emit_exp( emit, binary->lhs ); right = emit_engine_emit_exp( emit, binary->rhs ); // check if( !left || !right ) return FALSE; // emit the op if( !emit_engine_emit_op( emit, binary->op, binary->lhs, binary->rhs, binary ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_op() // desc: emit binary operator //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_op( Chuck_Emitter * emit, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { // any implicit cast happens before this Chuck_Type * t_left = lhs->cast_to ? lhs->cast_to : lhs->type; Chuck_Type * t_right = rhs->cast_to ? rhs->cast_to : rhs->type; // get the types of the left and right te_Type left = t_left->xid; te_Type right = t_right->xid; // op Chuck_Instr * instr = NULL; // emit op switch( op ) { // ----------------------------- num -------------------------------------- case ae_op_plus: // time + dur if( ( left == te_dur && right == te_time ) || ( left == te_time && right == te_dur ) ) { emit->append( instr = new Chuck_Instr_Add_double ); } // string + string else if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) { // concatenate emit->append( instr = new Chuck_Instr_Add_string ); } // left: string else if( isa( t_left, &t_string ) ) { // + int if( isa( t_right, &t_int ) ) emit->append( instr = new Chuck_Instr_Add_string_int ); else if( isa( t_right, &t_float ) ) emit->append( instr = new Chuck_Instr_Add_string_float ); else { EM_error2( lhs->linepos, "(emit): internal error: unhandled op '%s' %s '%s'", t_left->c_name(), op2str( op ), t_right->c_name() ); return FALSE; } } // right: string else if( isa( t_right, &t_string ) ) { // + int if( isa( t_left, &t_int ) ) emit->append( instr = new Chuck_Instr_Add_int_string ); else if( isa( t_left, &t_float ) ) emit->append( instr = new Chuck_Instr_Add_float_string ); else { EM_error2( lhs->linepos, "(emit): internal error: unhandled op '%s' %s '%s'", t_left->c_name(), op2str( op ), t_right->c_name() ); return FALSE; } } else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Add_int ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Add_double ); break; default: break; } } break; case ae_op_plus_chuck: // time + dur if( ( left == te_dur && right == te_time ) || ( left == te_time && right == te_dur ) ) { emit->append( instr = new Chuck_Instr_Add_double_Assign ); } // string + string else if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) { // concatenate emit->append( instr = new Chuck_Instr_Add_string_Assign ); } // right: string else if( isa( t_right, &t_string ) ) { // + int if( isa( t_left, &t_int ) ) emit->append( instr = new Chuck_Instr_Add_int_string_Assign ); else if( isa( t_left, &t_float ) ) emit->append( instr = new Chuck_Instr_Add_float_string_Assign ); else { EM_error2( lhs->linepos, "(emit): internal error: unhandled op '%s' %s '%s'", t_left->c_name(), op2str( op ), t_right->c_name() ); return FALSE; } } else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Add_int_Assign ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Add_double_Assign ); break; default: break; } } break; case ae_op_minus: if( ( left == te_time && right == te_dur ) ) // time - dur = time emit->append( instr = new Chuck_Instr_Minus_double ); else if( ( left == te_time && right == te_time ) ) // time - time = dur emit->append( instr = new Chuck_Instr_Minus_double ); else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Minus_int ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Minus_double ); break; default: break; } } break; case ae_op_minus_chuck: if( ( left == te_dur && right == te_time ) ) // time - dur = time emit->append( instr = new Chuck_Instr_Minus_double_Assign ); else if( ( left == te_time && right == te_time ) ) // time - time = dur emit->append( instr = new Chuck_Instr_Minus_double_Assign ); else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Minus_int_Assign ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Minus_double_Assign ); break; default: break; } } break; case ae_op_times: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Times_int ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Times_double ); break; default: break; } break; case ae_op_times_chuck: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Times_int_Assign ); break; case te_float: emit->append( instr = new Chuck_Instr_Times_double_Assign ); break; default: break; } break; case ae_op_divide: if( ( left == te_time && right == te_dur ) ) // time / dur = float emit->append( instr = new Chuck_Instr_Divide_double ); else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Divide_int ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Divide_double ); break; default: break; } } break; case ae_op_divide_chuck: // reverse if( ( left == te_dur && right == te_time ) ) // time / dur = float emit->append( instr = new Chuck_Instr_Divide_double_Assign ); else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Divide_int_Assign ); break; case te_float: emit->append( instr = new Chuck_Instr_Divide_double_Assign ); break; default: break; } } break; case ae_op_s_or: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Or ); break; default: break; } break; case ae_op_s_or_chuck: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Or_Assign ); break; default: break; } break; case ae_op_s_and: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_And ); break; default: break; } break; case ae_op_s_and_chuck: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_And_Assign ); break; default: break; } break; case ae_op_shift_left: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Shift_Left ); break; default: break; } break; case ae_op_shift_left_chuck: // reverse switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Shift_Left_Assign ); break; default: break; } break; case ae_op_shift_right: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Shift_Right ); break; default: break; } break; case ae_op_shift_right_chuck: // reverse switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Shift_Right_Assign ); break; default: break; } break; case ae_op_percent: if( ( left == te_time && right == te_dur ) ) // time % dur = dur { emit->append( instr = new Chuck_Instr_Mod_double ); } else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Mod_int ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Mod_double ); break; default: break; } } break; case ae_op_percent_chuck: // reverse if( ( left == te_dur && right == te_time ) ) // time % dur = dur { emit->append( instr = new Chuck_Instr_Mod_double_Assign ); } else // other types { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Mod_int_Assign ); break; case te_float: case te_dur: emit->append( instr = new Chuck_Instr_Mod_double_Assign ); break; default: break; } } break; case ae_op_s_xor: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Xor ); break; default: break; } break; case ae_op_s_xor_chuck: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Binary_Xor_Assign ); break; default: break; } break; // ----------------------------- chuck ------------------------------------- case ae_op_chuck: { a_Exp cl = lhs, cr = rhs; if( !emit_engine_emit_op_chuck( emit, cl, cr, binary ) ) return FALSE; return TRUE; } case ae_op_unchuck: { a_Exp cl = lhs, cr = rhs; // TODO: cross chuck assert( cl->next == NULL && cr->next == NULL ); while( cr ) { cl = lhs; while( cl ) { if( !emit_engine_emit_op_unchuck( emit, cl, cr ) ) return FALSE; cl = cl->next; } cr = cr->next; } return TRUE; } case ae_op_at_chuck: { a_Exp cl = lhs, cr = rhs; // TODO: cross chuck assert( cl->next == NULL && cr->next == NULL ); while( cr ) { cl = lhs; while( cl ) { if( !emit_engine_emit_op_at_chuck( emit, cl, cr ) ) return FALSE; cl = cl->next; } cr = cr->next; } return TRUE; } case ae_op_s_chuck: break; // -------------------------------- bool ----------------------------------- case ae_op_eq: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) && !isa( t_left, &t_null ) && !isa( t_right, &t_null ) ) // !null emit->append( instr = new Chuck_Instr_Op_string( op ) ); else if( isa( t_left, &t_object ) && isa( t_right, &t_object ) ) emit->append( instr = new Chuck_Instr_Eq_int ); else { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Eq_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Eq_double ); break; default: break; } } break; case ae_op_neq: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) emit->append( instr = new Chuck_Instr_Op_string( op ) ); else if( isa( t_left, &t_object ) && isa( t_right, &t_object ) ) emit->append( instr = new Chuck_Instr_Neq_int ); else { switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Neq_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Neq_double ); break; default: break; } } break; case ae_op_lt: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Lt_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Lt_double ); break; default: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) emit->append( instr = new Chuck_Instr_Op_string( op ) ); break; } break; case ae_op_le: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Le_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Le_double ); break; default: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) emit->append( instr = new Chuck_Instr_Op_string( op ) ); break; } break; case ae_op_gt: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Gt_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Gt_double ); break; default: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) emit->append( instr = new Chuck_Instr_Op_string( op ) ); break; } break; case ae_op_ge: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Ge_int ); break; case te_float: case te_dur: case te_time: emit->append( instr = new Chuck_Instr_Ge_double ); break; default: if( isa( t_left, &t_string ) && isa( t_right, &t_string ) ) emit->append( instr = new Chuck_Instr_Op_string( op ) ); break; } break; case ae_op_and: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_And ); break; default: break; } break; case ae_op_or: switch( left ) { case te_int: emit->append( instr = new Chuck_Instr_Or ); break; default: break; } break; default: EM_error2( lhs->linepos, "(emit): internal error: unhandled op '%s' %s '%s'", t_left->c_name(), op2str( op ), t_right->c_name() ); return FALSE; } // make sure emit if( !instr ) { EM_error2( lhs->linepos, "(emit): internal error: unhandled op '%s' %s '%s'", t_left->c_name(), op2str( op ), t_right->c_name() ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_op_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_op_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { // any implicit cast happens before this Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; // ugen => ugen if( isa( left, &t_ugen ) && isa( right, &t_ugen ) ) { // link emit->append( new Chuck_Instr_UGen_Link ); // done return TRUE; } // time advance if( isa( left, &t_dur ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var ) { // add the two emit->append( new Chuck_Instr_Add_double ); // see if rhs is 'now' if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) { // advance time emit->append( new Chuck_Instr_Time_Advance ); } return TRUE; } // time advance if( isa( left, &t_event ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var && rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) { // pop now emit->append( new Chuck_Instr_Reg_Pop_Word2 ); emit->append( new Chuck_Instr_Event_Wait ); return TRUE; } // func call if( isa( right, &t_function ) ) { assert( binary->ck_func != NULL ); // emit return emit_engine_emit_exp_func_call( emit, binary->ck_func, binary->self->type, binary->linepos ); } // assignment or something else if( isa( left, right ) ) { // basic types? if( type_engine_check_primitive( left ) || isa( left, &t_string ) ) { // use at assign return emit_engine_emit_op_at_chuck( emit, lhs, rhs ); } } // TODO: check overloading of => // TODO: deal with const // no match EM_error2( lhs->linepos, "(emit): internal error: unhandled '=>' on types '%s' and '%s'...", left->c_name(), right->c_name() ); return FALSE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_op_unchuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_op_unchuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ) { // any implicit cast happens before this Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; // if ugen if( isa( left, &t_ugen ) && isa( right, &t_ugen ) ) { // no connect emit->append( new Chuck_Instr_UGen_UnLink ); } else { EM_error2( lhs->linepos, "(emit): internal error: unhandled '=<' on types '%s' and '%s'", left->c_name(), right->c_name() ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_op_at_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_op_at_chuck( Chuck_Emitter * emit, a_Exp lhs, a_Exp rhs ) { // any implicit cast happens before this Chuck_Type * left = lhs->cast_to ? lhs->cast_to : lhs->type; Chuck_Type * right = rhs->cast_to ? rhs->cast_to : rhs->type; // assignment or something else if( isa( left, right ) ) { // basic types? if( type_engine_check_primitive( left ) || isa( left, &t_string ) ) { // assigment? if( rhs->s_meta != ae_meta_var ) { EM_error2( lhs->linepos, "(emit): internal error: assignment to non-variable..." ); return FALSE; } // see if rhs is 'now' - time => now if( rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) { // pop the now addr emit->append( new Chuck_Instr_Reg_Pop_Word2 ); // advance time emit->append( new Chuck_Instr_Time_Advance ); } else if( isa( left, &t_string ) ) // string { // assign string emit->append( new Chuck_Instr_Assign_String ); } else { // assign primitive if( right->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Assign_Primitive ); else if( right->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Assign_Primitive2 ); else { EM_error2( rhs->linepos, "(emit): internal error: assignment to type of size %i...", right->size ); } } return TRUE; } else // objects { // assign object emit->append( new Chuck_Instr_Assign_Object ); return TRUE; } } // TODO: check overloading of => // TODO: deal with const // no match EM_error2( lhs->linepos, "(emit): internal error: unhandled '@=>' on types '%s' and '%s'...", left->c_name(), right->c_name() ); return FALSE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_unary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_unary( Chuck_Emitter * emit, a_Exp_Unary unary ) { if( unary->op != ae_op_spork && !emit_engine_emit_exp( emit, unary->exp ) ) return FALSE; // get type Chuck_Type * t = unary->self->type; assert( t != NULL ); // emit the operator switch( unary->op ) { case ae_op_plusplus: // make sure assignment is legal if( unary->self->s_meta != ae_meta_var ) // TODO: const { EM_error2( unary->self->linepos, "(emit): target for '++' not mutable..." ); return FALSE; } // increment if( equals( unary->exp->type, &t_int ) ) emit->append( new Chuck_Instr_PreInc_int ); else { EM_error2( unary->linepos, "(emit): internal error: unhandled type '%s' for pre '++'' operator", unary->exp->type->c_name() ); return FALSE; } break; case ae_op_minusminus: // make sure assignment is legal if( unary->self->s_meta != ae_meta_var ) // TODO: const { EM_error2( unary->self->linepos, "(emit): target for '--' not mutable..." ); return FALSE; } // decrement if( equals( unary->exp->type, &t_int ) ) emit->append( new Chuck_Instr_PreDec_int ); else { EM_error2( unary->linepos, "(emit): internal error: unhandled type '%s' for pre '--' operator", unary->exp->type->c_name() ); return FALSE; } break; case ae_op_tilda: // complement if( equals( unary->exp->type, &t_int ) ) emit->append( new Chuck_Instr_Complement_int ); else { EM_error2( unary->linepos, "(emit): internal error: unhandled type '%s' for '~' operator", unary->exp->type->c_name() ); return FALSE; } break; case ae_op_exclamation: // ! if( equals( unary->exp->type, &t_int ) ) emit->append( new Chuck_Instr_Not_int ); else { EM_error2( unary->linepos, "(emit): internal error: unhandled type '%s' for '!' operator", unary->exp->type->c_name() ); return FALSE; } break; case ae_op_minus: // negate if( equals( unary->exp->type, &t_int ) ) emit->append( new Chuck_Instr_Negate_int ); else if( equals( unary->exp->type, &t_float ) ) emit->append( new Chuck_Instr_Negate_double ); else { EM_error2( unary->linepos, "(emit): internal error: unhandled type '%s' for unary '-' operator", unary->exp->type->c_name() ); return FALSE; } break; case ae_op_spork: // spork ~ func() if( unary->exp->s_type == ae_exp_func_call ) { if( !emit_engine_emit_spork( emit, &unary->exp->func_call ) ) return FALSE; } else { EM_error2( unary->linepos, "(emit): internal error: sporking non-function call..." ); return FALSE; } break; case ae_op_new: // if this is an object if( isobj( t ) ) { // instantiate object, including array if( !emit_engine_instantiate_object( emit, t, unary->array, unary->type->ref ) ) return FALSE; } break; default: EM_error2( unary->linepos, "(emit): internal error: unhandled unary op '%s", op2str( unary->op ) ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_primary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_primary( Chuck_Emitter * emit, a_Exp_Primary exp ) { t_CKUINT temp; t_CKDUR dur; Chuck_String * str = NULL; // find out exp switch( exp->s_type ) { case ae_primary_var: if( exp->var == insert_symbol( "now" ) ) { emit->append( new Chuck_Instr_Reg_Push_Now ); } else if( exp->var == insert_symbol( "this" ) ) { // TODO: verify this is in the right scope emit->append( new Chuck_Instr_Reg_Push_This ); } else if( exp->var == insert_symbol( "me" ) ) { emit->append( new Chuck_Instr_Reg_Push_Me ); } else if( exp->var == insert_symbol( "true" ) ) { emit->append( new Chuck_Instr_Reg_Push_Imm( 1 ) ); } else if( exp->var == insert_symbol( "false" ) ) { emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); } else if( exp->var == insert_symbol("maybe") ) { emit->append( new Chuck_Instr_Reg_Push_Maybe() ); } else if( exp->var == insert_symbol("null") || exp->var == insert_symbol("NULL") ) { emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); } else if( exp->var == insert_symbol( "pi" ) ) { double pi = 3.14159265358979323846; emit->append( new Chuck_Instr_Reg_Push_Imm2( pi ) ); } else if( exp->var == insert_symbol( "dac" ) ) { emit->append( new Chuck_Instr_DAC ); } else if( exp->var == insert_symbol( "adc" ) ) { emit->append( new Chuck_Instr_ADC ); } else if( exp->var == insert_symbol( "bunghole" ) ) { emit->append( new Chuck_Instr_Bunghole ); } else if( exp->var == insert_symbol( "blackhole" ) ) { emit->append( new Chuck_Instr_Bunghole ); } else if( emit->find_dur( S_name(exp->var), &dur ) ) { emit->append( new Chuck_Instr_Reg_Push_Imm2( dur ) ); } else { // emit the symbol return emit_engine_emit_symbol( emit, exp->var, exp->value, exp->self->emit_var, exp->linepos ); } break; case ae_primary_num: memcpy( &temp, &exp->num, sizeof(temp) ); emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) ); break; case ae_primary_float: emit->append( new Chuck_Instr_Reg_Push_Imm2( exp->fnum ) ); break; case ae_primary_str: // TODO: fix this str = new Chuck_String; initialize_object( str, &t_string ); str->str = exp->str; temp = (t_CKUINT)str; emit->append( new Chuck_Instr_Reg_Push_Imm( temp ) ); break; case ae_primary_array: if( !emit_engine_emit_array_lit( emit, exp->array ) ) return FALSE; break; case ae_primary_exp: if( !emit_engine_emit_exp( emit, exp->exp ) ) return FALSE; break; case ae_primary_hack: { a_Exp e = exp->exp; // emit the expression if( !emit_engine_emit_exp( emit, e ) ) return FALSE; std::vector types; while( e != NULL ) { types.push_back( e->type ); e = e->next; } // emit hack emit->append( new Chuck_Instr_Gack( types ) ); break; } } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_array_lit() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_array_lit( Chuck_Emitter * emit, a_Array_Sub array ) { // go through and emit the expressions if( !emit_engine_emit_exp( emit, array->exp_list ) ) return FALSE; // count the number a_Exp e = array->exp_list; t_CKUINT count = 0; // loop over while( e ) { count++; e = e->next; } // the type e = array->exp_list; Chuck_Type * type = e->cast_to ? e->cast_to : e->type; // construct array dynamically emit->append( new Chuck_Instr_Array_Init( type, count ) ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_cast() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_cast( Chuck_Emitter * emit, a_Exp_Cast cast ) { Chuck_Type * to = cast->self->type; Chuck_Type * from = cast->exp->type; // emit the exp if( !emit_engine_emit_exp( emit, cast->exp ) ) return FALSE; // the actual work to be done return emit_engine_emit_cast( emit, to, from ); } //----------------------------------------------------------------------------- // name: emit_engine_emit_cast() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_cast( Chuck_Emitter * emit, Chuck_Type * to, Chuck_Type * from ) { // if type is already the same if( equals( to, from ) ) return TRUE; // int to float if( equals( to, &t_int ) && equals( from, &t_float ) ) emit->append( new Chuck_Instr_Cast_double2int ); // float to int else if( equals( to, &t_float ) && equals( from, &t_int ) ) emit->append( new Chuck_Instr_Cast_int2double ); // up cast - do nothing else if( !isa( to, from ) && !isa( from, to ) ) { EM_error2( 0, "(emit): internal error: cannot cast type '%s' to '%s'", from->c_name(), to->c_name() ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_postfix() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_postfix( Chuck_Emitter * emit, a_Exp_Postfix postfix ) { // emit the exp if( !emit_engine_emit_exp( emit, postfix->exp ) ) return FALSE; // emit switch( postfix->op ) { case ae_op_plusplus: if( equals( postfix->exp->type, &t_int ) ) emit->append( new Chuck_Instr_PostInc_int ); else { EM_error2( postfix->linepos, "(emit): internal error: unhandled type '%s' for post '++' operator", postfix->exp->type->c_name() ); return FALSE; } break; case ae_op_minusminus: if( equals( postfix->exp->type, &t_int ) ) emit->append( new Chuck_Instr_PostDec_int ); else { EM_error2( postfix->linepos, "(emit): internal error: unhandled type '%s' for post '--' operator", postfix->exp->type->c_name() ); return FALSE; } break; default: EM_error2( postfix->linepos, "(emit): internal error: unhandled postfix operator '%s'", op2str( postfix->op ) ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_dur() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_dur( Chuck_Emitter * emit, a_Exp_Dur dur ) { // emit base if( !emit_engine_emit_exp( emit, dur->base ) ) return FALSE; // cast if( equals( dur->base->type, &t_int ) ) emit->append( new Chuck_Instr_Cast_int2double ); // emit unit if( !emit_engine_emit_exp( emit, dur->unit ) ) return FALSE; // multiply emit->append( new Chuck_Instr_Times_double ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_array() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_array( Chuck_Emitter * emit, a_Exp_Array array ) { Chuck_Type * type = NULL, * base_type = NULL; t_CKUINT depth = 0; a_Array_Sub sub = NULL; a_Exp exp = NULL; t_CKBOOL is_var = FALSE; t_CKBOOL is_str = FALSE; // get the type type = array->self->type; // get the base type base_type = array->base->type; // emit as addr? is_var = array->self->emit_var; // get the dimension depth = base_type->array_depth - type->array_depth; // make sure if( depth == 0 ) { EM_error2( array->linepos, "(emit): internal error: array with 0 depth..." ); return FALSE; } // get the sub sub = array->indices; if( !sub ) { EM_error2( array->linepos, "(emit): internal error: NULL array sub..." ); return FALSE; } // get the exp list exp = sub->exp_list; if( !exp ) { EM_error2( array->linepos, "(emit): internal error: NULL array exp..." ); return FALSE; } // emit the base (it should be a pointer to array) if( !emit_engine_emit_exp( emit, array->base ) ) return FALSE; // emit the exp list if( !emit_engine_emit_exp( emit, exp ) ) return FALSE; // find out first element if( isa( exp->type, &t_string ) ) is_str = TRUE; // make sure if( type->size != 4 && type->size != 8 ) // ISSUE: 64-bit { EM_error2( array->linepos, "(emit): internal error: array with datasize of %i...", type->size ); return FALSE; } // check the depth if( depth == 1 ) { // emit the array access if( is_str ) emit->append( new Chuck_Instr_Array_Map_Access( type->size, is_var ) ); else emit->append( new Chuck_Instr_Array_Access( type->size, is_var ) ); } else { // emit the multi array access emit->append( new Chuck_Instr_Array_Access_Multi( depth, type->size, is_var ) ); } // TODO: variable? return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, Chuck_Func * func, Chuck_Type * type, int linepos, t_CKBOOL spork ) { // is a member? t_CKBOOL is_member = func->is_member; // if member //if( is_member ) //{ // // this // emit->append( new Chuck_Instr_Reg_Push_This ); //} // translate to code emit->append( new Chuck_Instr_Func_To_Code ); // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)func->code ) ); // push the local stack depth - local variables emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) ); // TODO: member functions and static functions // call the function t_CKUINT size = type->size; if( func->def->s_type == ae_func_builtin ) { if( size == 0 || size == 4 || size == 8 ) // ISSUE: 64-bit { // is member if( is_member ) emit->append( new Chuck_Instr_Func_Call_Member( size ) ); else emit->append( new Chuck_Instr_Func_Call_Static( size ) ); } else { EM_error2( linepos, "(emit): internal error: %i func call not handled", size ); return FALSE; } } else { emit->append( new Chuck_Instr_Func_Call ); } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_func_args() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_func_args( Chuck_Emitter * emit, a_Exp_Func_Call func_call ) { // emit the args if( !emit_engine_emit_exp( emit, func_call->args ) ) { EM_error2( func_call->linepos, "(emit): internal error in emitting function call arguments..." ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_func_call( Chuck_Emitter * emit, a_Exp_Func_Call func_call, t_CKBOOL spork ) { // note: spork situations are now taken care in exp_spork... // please look at that one before modifying this one! // make sure there are args, and not sporking if( func_call->args && !spork ) { if( !emit_engine_emit_func_args( emit, func_call ) ) return FALSE; } // emit func if( !emit_engine_emit_exp( emit, func_call->func ) ) { EM_error2( func_call->linepos, "(emit): internal error in evaluating function call..." ); return FALSE; } // the rest return emit_engine_emit_exp_func_call( emit, func_call->ck_func, func_call->ret_type, func_call->linepos, spork ); } //----------------------------------------------------------------------------- // name: emit_engine_emit_dot_member() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_dot_member( Chuck_Emitter * emit, a_Exp_Dot_Member member ) { // the type of the base Chuck_Type * t_base = NULL; // whether to emit addr or value t_CKBOOL emit_addr = member->self->emit_var; // is the base a class/namespace or a variable t_CKBOOL base_static = isa( member->t_base, &t_class ); // a function Chuck_Func * func = NULL; // a non-function value Chuck_Value * value = NULL; // the offset t_CKUINT offset = 0; // actual type - if base is class name its type is actually 'class' // to get the actual type use actual_type t_base = base_static ? member->t_base->actual_type : member->t_base; // make sure that the base type is object assert( t_base->info != NULL ); // if base is static if( !base_static ) { // if is a func if( isfunc( member->self->type ) ) { // get the func value = type_engine_find_value( t_base, member->xid ); func = value->func_ref; // make sure it's there assert( func != NULL ); // is the func static? if( func->is_member ) { // emit the base emit_engine_emit_exp( emit, member->base ); // dup the base pointer emit->append( new Chuck_Instr_Reg_Dup_Last ); // find the offset for virtual table offset = func->vt_index; // emit the function emit->append( new Chuck_Instr_Dot_Member_Func( offset ) ); } else { // emit the type emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); // emit the static function emit->append( new Chuck_Instr_Dot_Static_Func( func ) ); } } else { // get the value // value = t_base->info->lookup_value( member->xid, FALSE ); value = type_engine_find_value( t_base, member->xid ); // make sure it's there assert( value != NULL ); // find the offset for data offset = value->offset; // is the value static? if( value->is_member ) { // emit the base emit_engine_emit_exp( emit, member->base ); // lookup the member emit->append( new Chuck_Instr_Dot_Member_Data( offset, member->self->type->size, emit_addr ) ); } else { // if builtin or not if( value->addr ) { // emit builtin emit->append( new Chuck_Instr_Dot_Static_Import_Data( value->addr, member->self->type->size, emit_addr ) ); } else { // emit the type emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); // emit the static value emit->append( new Chuck_Instr_Dot_Static_Data( offset, member->self->type->size, emit_addr ) ); } } } } else // static { // emit the type // commented out so built-in static member variables don't have an // extra thing on the stack - spencer //emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); // if is a func if( isfunc( member->self->type ) ) { // emit the type - spencer emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); // get the func func = t_base->info->lookup_func( member->xid, FALSE ); // make sure it's there assert( func != NULL ); // emit the function emit->append( new Chuck_Instr_Dot_Static_Func( func ) ); } else { // get the value value = t_base->info->lookup_value( member->xid, FALSE ); // make sure it's there assert( value != NULL ); // if builtin if( value->addr ) { // emit emit->append( new Chuck_Instr_Dot_Static_Import_Data( value->addr, member->self->type->size, emit_addr ) ); } else { // emit the type - spencer emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)t_base ) ); // find the offset for data offset = value->offset; // emit the member emit->append( new Chuck_Instr_Dot_Static_Data( offset, member->self->type->size, emit_addr ) ); } } } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_if( Chuck_Emitter * emit, a_Exp_If exp_if ) { t_CKBOOL ret = TRUE; Chuck_Instr_Branch_Op * op = NULL, * op2 = NULL; // push the stack, allowing for new local variables emit->push_scope(); // emit the condition ret = emit_engine_emit_exp( emit, exp_if->cond ); if( !ret ) return FALSE; // type of the condition switch( exp_if->cond->type->xid ) { case te_int: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); op = new Chuck_Instr_Branch_Eq_int( 0 ); break; case te_float: case te_dur: case te_time: // push 0 emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); op = new Chuck_Instr_Branch_Eq_double( 0 ); break; default: EM_error2( exp_if->cond->linepos, "(emit): internal error: unhandled type '%s' in if condition", exp_if->cond->type->name.c_str() ); return FALSE; } if( !ret ) return FALSE; // append the op emit->append( op ); // emit the body ret = emit_engine_emit_exp( emit, exp_if->if_exp ); if( !ret ) return FALSE; // emit the skip to the end emit->append( op2 = new Chuck_Instr_Goto(0) ); // set the op's target op->set( emit->next_index() ); // emit the body ret = emit_engine_emit_exp( emit, exp_if->else_exp ); if( !ret ) return FALSE; // pop stack emit->pop_scope(); // set the op2's target op2->set( emit->next_index() ); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_pre_constructor() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_pre_constructor( Chuck_Emitter * emit, Chuck_Type * type ) { // parent first pre constructor if( type->parent != NULL ) emit_engine_pre_constructor( emit, type->parent ); // pre constructor if( type->has_constructor ) { // make sure assert( type->info->pre_ctor != NULL ); // append instruction emit->append( new Chuck_Instr_Pre_Constructor( type->info->pre_ctor, emit->code->frame->curr_offset ) ); } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_pre_constructor_array() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_pre_constructor_array( Chuck_Emitter * emit, Chuck_Type * type ) { // alloc should have put all objects to made in linear list, on stack Chuck_Instr_Pre_Ctor_Array_Top * top = NULL; Chuck_Instr_Pre_Ctor_Array_Bottom * bottom = NULL; // get start index t_CKUINT start_index = emit->next_index(); // append first part of pre ctor emit->append( top = new Chuck_Instr_Pre_Ctor_Array_Top( type ) ); // call pre constructor emit_engine_pre_constructor( emit, type ); // append second part of the pre ctor emit->append( bottom = new Chuck_Instr_Pre_Ctor_Array_Bottom ); // set the goto of the first one top->set( emit->next_index() ); // set the goto for the second one bottom->set( start_index ); // clean up code emit->append( new Chuck_Instr_Pre_Ctor_Array_Post ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_instantiate_object() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, a_Array_Sub array, t_CKBOOL is_ref ) { // if array if( type->array_depth ) { // emit indices emit_engine_emit_exp( emit, array->exp_list ); // emit array allocation emit->append( new Chuck_Instr_Array_Alloc( type->array_depth, type->array_type, emit->code->frame->curr_offset, is_ref ) ); // handle constructor if( isobj( type->array_type ) && !is_ref ) { // call pre constructor for array emit_engine_pre_constructor_array( emit, type->array_type ); } } else if( !is_ref ) // not array { // emit object instantiation code, include pre constructor emit->append( new Chuck_Instr_Instantiate_Object( type ) ); // call pre constructor emit_engine_pre_constructor( emit, type ); } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_exp_decl() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_exp_decl( Chuck_Emitter * emit, a_Exp_Decl decl, t_CKBOOL first_exp ) { a_Var_Decl_List list = decl->var_decl_list; a_Var_Decl var_decl = NULL; Chuck_Value * value = NULL; Chuck_Type * type = NULL; Chuck_Local * local = NULL; t_CKBOOL is_obj = FALSE; t_CKBOOL is_ref = FALSE; t_CKBOOL is_init = FALSE; // loop through vars while( list ) { // the var var_decl = list->var_decl; // get the value determined in type checker value = var_decl->value; // get the type of the value type = value->type; // is the variable a reference is_obj = isobj( type ); // do alloc or not is_ref = decl->type->ref; // not init is_init = FALSE; // if this is an object if( is_obj ) { // if array, then check to see if empty [] if( list->var_decl->array ) { if( list->var_decl->array->exp_list ) { // set is_init = TRUE; // instantiate object, including array if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) ) return FALSE; } } else if( !is_ref ) { // set is_init = TRUE; // instantiate object (not array) if( !emit_engine_instantiate_object( emit, type, list->var_decl->array, is_ref ) ) return FALSE; } } // if not init and first exp /* if( !is_init && first_exp ) { // push 0 if( type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Push_Imm( 0 ) ); else if( type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Push_Imm2( 0.0 ) ); else { EM_error2( decl->linepos, "(emit): unhandle decl size of '%i'...", type->size ); return FALSE; } }*/ // put in the value // member if( value->is_member ) { // zero out location in object, and leave addr on operand stack if( type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Alloc_Member_Word( value->offset ) ); else if( type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Alloc_Member_Word2( value->offset ) ); else { EM_error2( decl->linepos, "(emit): unhandle decl size of '%i'...", type->size ); return FALSE; } } else // not member { // not in class if( !emit->env->class_def || !decl->is_static ) { // allocate a place on the local stack local = emit->alloc_local( type->size, value->name, is_ref ); if( !local ) { EM_error2( decl->linepos, "(emit): internal error: cannot allocate local '%s'...", value->name.c_str() ); return FALSE; } // put in the value value->offset = local->offset; // zero out location in memory, and leave addr on operand stack // TODO: this is wrong for static // BAD: // FIX: if( type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Alloc_Word( local->offset ) ); else if( type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Alloc_Word2( local->offset ) ); else { EM_error2( decl->linepos, "(emit): unhandle decl size of '%i'...", type->size ); return FALSE; } } else // static { // emit the type emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)emit->env->class_def ) ); // emit the static value emit->append( new Chuck_Instr_Dot_Static_Data( value->offset, value->type->size, TRUE ) ); } } // set is_init is_init = FALSE; // if object, assign if( is_obj ) { // if array if( var_decl->array ) { // if not [] if( var_decl->array->exp_list ) { // set is_init = TRUE; // assign emit->append( new Chuck_Instr_Assign_Object ); } } else if( !is_ref ) { // set is_init = TRUE; // assign the object emit->append( new Chuck_Instr_Assign_Object ); } } // if not init and first exp /* if( !is_init && first_exp ) { // if obj if( is_obj ) emit->append( new Chuck_Instr_Assign_Object ); // size 4 primitive else if( type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Assign_Primitive ); // size 8 primitive else if( type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Assign_Primitive2 ); else assert( FALSE ); }*/ list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_code_segment() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_code_segment( Chuck_Emitter * emit, a_Stmt_Code stmt, t_CKBOOL push ) { a_Stmt_List list = stmt->stmt_list; // loop through while( list ) { // emit the statement if( !emit_engine_emit_stmt( emit, list->stmt ) ) return FALSE; // next list = list->next; } // TODO: push return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_func_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_func_def( Chuck_Emitter * emit, a_Func_Def func_def ) { // get the func Chuck_Func * func = func_def->ck_func; // get the value Chuck_Value * value = func->value_ref; // get the type Chuck_Type * type = value->type; // local Chuck_Local * local = NULL; // make sure it's the same one //Chuck_Func * func2 = emit->env->context->nspc.lookup_func( func_def->name, FALSE ); //if( func != func2 ) //{ // EM_error2( func_def->linepos, // "(emit): ambiguous function resolution for %s...", // S_name(func_def->name) ); // return FALSE; //} // make sure the code is empty if( func->code != NULL ) { EM_error2( func_def->linepos, "(emit): function '%s' already emitted...", S_name(func_def->name) ); return FALSE; } // make sure we are not in a function already if( emit->env->func != NULL ) { EM_error2( func_def->linepos, "(emit): internal error: nested function definition..." ); return FALSE; } // if not part of a class if( !emit->env->class_def ) { // put function on stack local = emit->alloc_local( value->type->size, value->name, TRUE ); // remember the offset value->offset = local->offset; // write to mem stack emit->append( new Chuck_Instr_Mem_Set_Imm( value->offset, (t_CKUINT)func ) ); } // set the func emit->env->func = func; // push the current code emit->stack.push_back( emit->code ); // make a new one emit->code = new Chuck_Code; // name the code emit->code->name = emit->env->class_def ? emit->env->class_def->name + "." : ""; emit->code->name += func->name + "( ... )"; // set whether need this emit->code->need_this = func->is_member; // go through the args a_Arg_List a = func_def->arg_list; t_CKBOOL is_ref = FALSE; // if member (non-static) function if( func->is_member ) { // get the size emit->code->stack_depth += sizeof(t_CKUINT); // add this if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE ) ) { EM_error2( a->linepos, "(emit): internal error: cannot allocate local 'this'..." ); return FALSE; } } // loop through args while( a ) { // get the value value = a->var_decl->value; // get the type type = value->type; // get ref is_ref = a->type_decl->ref; // get the size emit->code->stack_depth += type->size; // allocate a place on the local stack local = emit->alloc_local( type->size, value->name, is_ref ); if( !local ) { EM_error2( a->linepos, "(emit): internal error: cannot allocate local '%s'...", value->name.c_str() ); return FALSE; } // remember the offset value->offset = local->offset; // advance a = a->next; } // TODO: make sure the calculated stack depth is the same as func_def->stack depth // taking into account member function // emit the code if( !emit_engine_emit_stmt( emit, func_def->code, FALSE ) ) return FALSE; // set the index for next instruction for return statements for( t_CKUINT i = 0; i < emit->code->stack_return.size(); i++ ) emit->code->stack_return[i]->set( emit->next_index() ); // clear the return stack emit->code->stack_return.clear(); // emit return statement emit->append( new Chuck_Instr_Func_Return ); // vm code func->code = emit_to_code( emit->code, NULL, emit->dump ); // add reference func->code->add_ref(); // unset the func emit->env->func = NULL; // delete the code SAFE_DELETE( emit->code ); // pop the code assert( emit->stack.size() ); emit->code = emit->stack.back(); emit->stack.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_class_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_class_def( Chuck_Emitter * emit, a_Class_Def class_def ) { // get the type Chuck_Type * type = class_def->type; // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // make sure the code is empty if( type->info->pre_ctor != NULL && type->info->pre_ctor->instr != NULL ) { EM_error2( class_def->linepos, "(emit): class '%s' already emitted...", type->name.c_str() ); return FALSE; } // make sure we are not in a class already //if( emit->env->class_def != NULL ) //{ // EM_error2( class_def->linepos, // "(emit): internal error: nested class definition..." ); // return FALSE; //} // set the class emit->env->class_stack.push_back( emit->env->class_def ); emit->env->class_def = type; // push the current code emit->stack.push_back( emit->code ); // make a new one emit->code = new Chuck_Code; // name the code emit->code->name = string("class ") + type->name; // whether code needs this emit->code->need_this = TRUE; // if has constructor // if( type->has_constructor ) type->info->pre_ctor = new Chuck_VM_Code; // get the size emit->code->stack_depth += sizeof(t_CKUINT); // add this if( !emit->alloc_local( sizeof(t_CKUINT), "this", TRUE ) ) { EM_error2( class_def->linepos, "(emit): internal error: cannot allocate local 'this'..." ); return FALSE; } // emit the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: ret = emit_engine_emit_stmt_list( emit, body->section->stmt_list ); break; case ae_section_func: ret = emit_engine_emit_func_def( emit, body->section->func_def ); break; case ae_section_class: ret = emit_engine_emit_class_def( emit, body->section->class_def ); //EM_error2( body->section->class_def->linepos, // "nested class definitions are not yet supported..." ); //ret = FALSE; break; } // move to the next section body = body->next; } // if ok if( ret ) { // emit return statement emit->append( new Chuck_Instr_Func_Return ); // vm code type->info->pre_ctor = emit_to_code( emit->code, type->info->pre_ctor, emit->dump ); // add reference type->info->pre_ctor->add_ref(); // allocate static type->info->class_data = new t_CKBYTE[type->info->class_data_size]; // verify if( !type->info->class_data ) { // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while allocating static data '%s'\n", type->c_name() ); // flag ret = FALSE; } else { // zero it out memset( type->info->class_data, 0, type->info->class_data_size ); } } // check again if( !ret ) { // clean SAFE_DELETE( type->info->pre_ctor ); } // unset the class emit->env->class_def = emit->env->class_stack.back(); emit->env->class_stack.pop_back(); // delete the code SAFE_DELETE( emit->code ); // pop the code assert( emit->stack.size() ); emit->code = emit->stack.back(); emit->stack.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: emit_engine_emit_spork() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_spork( Chuck_Emitter * emit, a_Exp_Func_Call exp ) { // spork Chuck_Instr_Mem_Push_Imm * op = NULL; // if member function, push this // TODO: this is a hack - what if exp is not func_call? // if( exp->ck_func->is_member ) // emit->append( new Chuck_Instr_Reg_Push_This ); // evaluate args on sporker shred if( !emit_engine_emit_func_args( emit, exp ) ) return FALSE; // emit func pointer on sporker shred if( !emit_engine_emit_exp( emit, exp->func ) ) { EM_error2( exp->linepos, "(emit): internal error in evaluating function call..." ); return FALSE; } // push the current code emit->stack.push_back( emit->code ); // make a new one (spork~exp shred) emit->code = new Chuck_Code; // handle need this emit->code->need_this = exp->ck_func->is_member; // name it emit->code->name = "spork~exp"; // push op op = new Chuck_Instr_Mem_Push_Imm( 0 ); // emit the stack depth - we don't know this yet emit->append( op ); // call the func on sporkee shred if( !emit_engine_emit_exp_func_call( emit, exp->ck_func, exp->ret_type, exp->linepos, TRUE ) ) return FALSE; // emit the function call, with special flag // if( !emit_engine_emit_exp_func_call( emit, exp, TRUE ) ) // return FALSE; // done emit->append( new Chuck_Instr_EOC ); // set the stack depth now that we know op->set( emit->code->stack_depth ); // emit it Chuck_VM_Code * code = emit_to_code( emit->code, NULL, emit->dump ); // remember it exp->ck_vm_code = code; // add reference exp->ck_vm_code->add_ref(); // code->name = string("spork~exp"); // restore the code to sporker shred assert( emit->stack.size() > 0 ); emit->code = emit->stack.back(); // pop emit->stack.pop_back(); a_Exp e = exp->args; t_CKUINT size = 0; while( e ) { size += e->cast_to ? e->cast_to->size : e->type->size; e = e->next; } // handle member function // TODO: this is a hack - what if exp is not func_call? // if( emit->code->need_this ) // size += 4; // emit instruction that will put the code on the stack emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)code ) ); // emit spork instruction - this will copy, func, args, this emit->append( new Chuck_Instr_Spork( size ) ); return TRUE; } //----------------------------------------------------------------------------- // name: emit_engine_emit_symbol() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_emit_symbol( Chuck_Emitter * emit, S_Symbol symbol, Chuck_Value * v, t_CKBOOL emit_var, int linepos ) { // look up the value // Chuck_Value * v = emit->env->curr->lookup_value( symbol, TRUE ); // it should be there if( !v ) { // internal error EM_error2( linepos, "(emit): internal error: undefined symbol '%s'...", S_name(symbol) ); return FALSE; } // if part of class - this only works because x.y is handled separately if( v->owner_class && (v->is_member || v->is_static) ) { // make sure talking about the same class // this doesn't work since the owner class could be a super class // assert( v->owner_class == emit->env->class_def ); // // try this (thanks Robin Davies) assert( isa( emit->env->class_def, v->owner_class ) /* || is_global( v->owner_class ) */ ); // emit as this.v a_Exp base = new_exp_from_id( "this", linepos ); a_Exp dot = new_exp_from_member_dot( base, (char *)v->name.c_str(), linepos ); base->type = v->owner_class; dot->type = v->type; dot->dot_member.t_base = v->owner_class; dot->emit_var = emit_var; // emit it if( !emit_engine_emit_exp_dot_member( emit, &dot->dot_member ) ) { // internal error EM_error2( linepos, "(emit): internal error: symbol transformation failed..." ); return FALSE; } return TRUE; } // var or value if( emit_var ) { // emit as addr emit->append( new Chuck_Instr_Reg_Push_Mem_Addr( v->offset, v->is_context_global ) ); } else { // special case if( v->func_ref ) emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)v->func_ref ) ); // check size else if( v->type->size == 4 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Push_Mem( v->offset, v->is_context_global ) ); else if( v->type->size == 8 ) // ISSUE: 64-bit emit->append( new Chuck_Instr_Reg_Push_Mem2( v->offset, v->is_context_global ) ); else { // internal error EM_error2( linepos, "(emit): internal error: symbol '%s' has size '%i'...", S_name(symbol), v->type->size ); return FALSE; } } return TRUE; } //----------------------------------------------------------------------------- // name: pop_scope() // desc: ... //----------------------------------------------------------------------------- void Chuck_Emitter::pop_scope( ) { // sanity assert( code != NULL ); // clear locals locals.clear(); // get locals code->frame->pop_scope( locals ); // TODO: free locals } //----------------------------------------------------------------------------- // name: find_dur() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Emitter::find_dur( const string & name, t_CKDUR * out ) { // sanity assert( env != NULL ); assert( out != NULL ); // zero *out = 0.0; // get value from env Chuck_Value * value = env->global()->lookup_value( name, FALSE ); if( !value || !equals( value->type, &t_dur ) ) return FALSE; // copy *out = *( (t_CKDUR *)value->addr ); return TRUE; } /* //----------------------------------------------------------------------------- // name: emit_engine_instantiate_object() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL emit_engine_instantiate_object( Chuck_Emitter * emit, Chuck_Type * type, a_Array_Sub array, t_CKBOOL is_ref ) { // if array if( type->array_depth ) { // emit indices emit_engine_emit_exp( emit, array->exp_list ); // emit array allocation emit->append( new Chuck_Instr_Array_Alloc( type->array_depth, type->array_type, emit->code->frame->curr_offset, is_ref ) ); // handle constructor //if( isobj( type->array_type ) && !is_ref ) //{ // // TODO: // EM_error2( array->linepos, "internal error: object array constructor not impl..." ); // return FALSE; //} } else if( !is_ref ) // not array { // if ugen //if( isa( type, &t_ugen ) ) //{ // // get the ugen info // Chuck_UGen_Info * info = decl->self->type->ugen; // if( !info ) // { // EM_error2( decl->linepos, // "(emit): internal error: undefined ugen type '%s'", // type->name.c_str() ); // return FALSE; // } // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)info ) ); // emit->append( new Chuck_Instr_UGen_Alloc() ); //} //else //{ // emit object instantiation code, include pre constructor emit->append( new Chuck_Instr_Instantiate_Object( type ) ); //} // call pre constructor emit_engine_pre_constructor( emit, type ); // constructor //if( type->has_constructor ) //{ // // make sure // assert( type->info->pre_ctor != NULL ); // // push this // emit->append( new Chuck_Instr_Reg_Dup_Last ); // // push pre-constructor // emit->append( new Chuck_Instr_Reg_Push_Imm( (t_CKUINT)type->info->pre_ctor ) ); // // push frame offset // emit->append( new Chuck_Instr_Reg_Push_Imm( emit->code->frame->curr_offset ) ); // // call the function // if( type->info->pre_ctor->native_func != NULL ) // emit->append( new Chuck_Instr_Func_Call_Member( 0 ) ); // else // emit->append( new Chuck_Instr_Func_Call ); //} } return TRUE; }*/ chuck-1.2.0.8.dfsg/src/chuck_emit.h0000644000175000017500000001147510600421722015422 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_emit.h // desc: chuck instruction emitter // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 - first version // Autumn 2004 - redesign //----------------------------------------------------------------------------- #ifndef __CHUCK_EMIT_H__ #define __CHUCK_EMIT_H__ #include "chuck_def.h" #include "chuck_oo.h" #include "chuck_type.h" #include "chuck_frame.h" // forward references struct Chuck_Instr; struct Chuck_Instr_Goto; struct Chuck_VM_Code; struct Chuck_VM_Shred; //----------------------------------------------------------------------------- // name: struct Chuck_Code // desc: ... //----------------------------------------------------------------------------- struct Chuck_Code { public: // name std::string name; // stack depth t_CKUINT stack_depth; // need this t_CKBOOL need_this; // frame Chuck_Frame * frame; // code std::vector code; // continue stack std::vector stack_cont; // break stack std::vector stack_break; // return stack std::vector stack_return; // constructor Chuck_Code( ) { stack_depth = 0; need_this = FALSE; frame = new Chuck_Frame; } // destructor ~Chuck_Code() { delete frame; frame = NULL; } }; //----------------------------------------------------------------------------- // name: struct Chuck_Emitter // desc: ... //----------------------------------------------------------------------------- struct Chuck_Emitter : public Chuck_VM_Object { // reference to the type checker environment Chuck_Env * env; // reference to VM Chuck_VM * vm; // current code Chuck_Code * code; // current context Chuck_Context * context; // expression namespace Chuck_Namespace * nspc; // current function definition Chuck_Func * func; // code stack std::vector stack; // locals std::vector locals; // dump t_CKBOOL dump; // constructor Chuck_Emitter() { env = NULL; vm = NULL; code = NULL; context = NULL; nspc = NULL; func = NULL; dump = FALSE; } // destructor ~Chuck_Emitter() { } // append instruction void append( Chuck_Instr * instr ) { assert( code != NULL ); code->code.push_back( instr ); } // index t_CKUINT next_index() { assert( code != NULL ); return code->code.size(); } // push scope void push_scope( ) { assert( code != NULL ); code->frame->push_scope(); } // alloc local Chuck_Local * alloc_local( t_CKUINT size, const std::string & name, t_CKBOOL is_ref ) { assert( code != NULL ); return code->frame->alloc_local( size, name, is_ref ); } // pop scope void pop_scope( ); // default durations t_CKBOOL find_dur( const std::string & name, t_CKDUR * out ); }; // allocate the emitter Chuck_Emitter * emit_engine_init( Chuck_Env * env ); // shutdown and free the emitter t_CKBOOL emit_engine_shutdown( Chuck_Emitter *& emit ); // emit a program into vm code Chuck_VM_Code * emit_engine_emit_prog( Chuck_Emitter * emit, a_Program prog, te_HowMuch how_much = te_do_all ); // helper function to emit code Chuck_VM_Code * emit_to_code( Chuck_Code * in, Chuck_VM_Code * out = NULL, t_CKBOOL dump = FALSE ); // NOT USED: ... t_CKBOOL emit_engine_addr_map( Chuck_Emitter * emit, Chuck_VM_Shred * shred ); t_CKBOOL emit_engine_resolve( ); #endif chuck-1.2.0.8.dfsg/src/chuck_errmsg.cpp0000644000175000017500000001663510600421722016321 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: errmsg.cpp // desc: functions used in all phases of the compiler to give error messages // about the Tiger program. (now ChucK) // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include #include #include #include "chuck_utils.h" #include "chuck_errmsg.h" #include "util_thread.h" // global int EM_tokPos = 0; int EM_lineNum = 1; t_CKBOOL anyErrors= FALSE; // local global static const char * fileName = ""; static int lineNum = 1; static char g_buffer[1024] = ""; static char g_lasterror[1024] = "[chuck]: (no error)"; // log globals int g_loglevel = CK_LOG_CORE; int g_logstack = 0; XMutex g_logmutex; // name static const char * g_str[] = { "NONE", // 0 "CKCORE", // 1 "SYSTEM", // 2 "SEVERE", // 3 "WARN!!", // 4 "INFORM", // 5 "CONFIG", // 6 "FINE!!", // 7 "FINER!", // 8 "FINEST", // 9 "ALL!!" // 10 }; // intList typedef struct intList {int i; struct intList *rest;} *IntList; static IntList linePos=NULL; // constructor static IntList intList( int i, IntList rest ) { IntList l = (IntList)checked_malloc(sizeof *l); l->i=i; l->rest=rest; return l; } // new line in lexer void EM_newline(void) { lineNum++; EM_lineNum++; linePos = intList(EM_tokPos, linePos); } // content after rightmost '/' const char * mini( const char * str ) { int len = strlen( str ); const char * p = str + len; while( p != str && *p != '/' && *p != '\\' ) p--; return ( p == str || strlen(p+1) == 0 ? p : p+1 ); } // content after 'struct' const char * mini_type( const char * str ) { if( !strncmp( str, "struct ", 7 ) ) str += 7; const char * p = str; while( *p && *p >= '0' && *p <= '9' ) p++; return p; } // [%s]:line(%d).char(%d): void EM_error( int pos, const char * message, ... ) { va_list ap; IntList lines = linePos; int num = lineNum; anyErrors = TRUE; while( lines && lines->i >= pos ) { lines = lines->rest; num--; } fprintf( stderr, "[%s]:", *fileName ? mini(fileName) : "chuck" ); sprintf( g_lasterror, "[%s]:", *fileName ? mini(fileName) : "chuck" ); if(lines) { fprintf(stderr, "line(%d).char(%d):", num, pos-lines->i ); sprintf( g_buffer, "line(%d).char(%d):", num, pos-lines->i ); strcat( g_lasterror, g_buffer ); } fprintf(stderr, " " ); strcat( g_lasterror, " " ); va_start(ap, message); vfprintf(stderr, message, ap); vsprintf( g_buffer, message, ap ); va_end(ap); fprintf(stderr, "\n"); fflush( stderr ); strcat( g_lasterror, g_buffer ); } // [%s]:line(%d): void EM_error2( int line, const char * message, ... ) { va_list ap; fprintf( stderr, "[%s]:", *fileName ? mini(fileName) : "chuck" ); sprintf( g_lasterror, "[%s]:", *fileName ? mini(fileName) : "chuck" ); if(line) { fprintf( stderr, "line(%d):", line ); sprintf( g_buffer, "line(%d):", line ); strcat( g_lasterror, g_buffer ); } fprintf( stderr, " " ); strcat( g_lasterror, " " ); va_start( ap, message ); vfprintf( stderr, message, ap ); vsprintf( g_buffer, message, ap ); va_end( ap ); strcat( g_lasterror, g_buffer ); fprintf( stderr, "\n" ); fflush( stderr ); } // [%s]:line(%d): void EM_error2b( int line, const char * message, ... ) { va_list ap; fprintf( stderr, "[%s]:", *fileName ? mini(fileName) : "chuck" ); sprintf( g_lasterror, "[%s]:", *fileName ? mini(fileName) : "chuck" ); if(line) { fprintf( stderr, "line(%d):", line ); sprintf( g_buffer, "line(%d):", line ); strcat( g_lasterror, g_buffer ); } fprintf( stderr, " " ); strcat( g_lasterror, " " ); va_start( ap, message ); vfprintf( stderr, message, ap ); vsprintf( g_buffer, message, ap ); va_end( ap ); strcat( g_lasterror, g_buffer ); fprintf( stdout, "\n" ); fflush( stderr ); } // void EM_error3( const char * message, ... ) { va_list ap; g_lasterror[0] = '\0'; g_buffer[0] = '\0'; va_start( ap, message ); vfprintf( stderr, message, ap ); vsprintf( g_buffer, message, ap ); va_end( ap ); strcat( g_lasterror, g_buffer ); fprintf( stderr, "\n" ); fflush( stderr ); } // log void EM_log( int level, const char * message, ... ) { va_list ap; if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY; else if( level <= CK_LOG_NONE ) level = CK_LOG_NONE + 1; // check level if( level > g_loglevel ) return; g_logmutex.acquire(); fprintf( stderr, "[chuck]:" ); fprintf( stderr, "(%i:%s): ", level, g_str[level] ); // if( g_logstack ) fprintf( stderr, " " ); for( int i = 0; i < g_logstack; i++ ) fprintf( stderr, " | " ); va_start( ap, message ); vfprintf( stderr, message, ap ); va_end( ap ); fprintf( stderr, "\n" ); fflush( stderr ); g_logmutex.release(); } // set log level void EM_setlog( int level ) { if( level > CK_LOG_CRAZY ) level = CK_LOG_CRAZY; else if( level < CK_LOG_NONE ) level = CK_LOG_NONE; g_loglevel = level; // log this EM_log( CK_LOG_SYSTEM, "setting log level to: %i (%s)...", level, g_str[level] ); } // push log void EM_pushlog() { g_logstack++; } // pop log void EM_poplog() { g_logstack--; if( g_logstack < 0 ) g_logstack = 0; } // prepare new file t_CKBOOL EM_reset( const char * fname, FILE * fd ) { anyErrors = FALSE; fileName = fname ? fname : (c_str)""; lineNum = 1; EM_lineNum = 1; // free the intList IntList curr = NULL; while( linePos ) { curr = linePos; linePos = linePos->rest; // free free( curr ); } // make new intList linePos = intList( 0, NULL ); return TRUE; } // change file void EM_change_file( const char * fname ) { // set fileName = fname ? fname : (c_str)""; // more set lineNum = 0; EM_lineNum = 0; } // return last error const char * EM_lasterror() { return g_lasterror; } chuck-1.2.0.8.dfsg/src/chuck_errmsg.h0000644000175000017500000000546510600421722015765 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_errmsg.h // desc: error msg // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang.cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_ERRORMSG_H__ #define __CHUCK_ERRORMSG_H__ #include "chuck_def.h" #include #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif extern t_CKBOOL EM_anyErrors; extern int EM_tokPos; extern int EM_lineNum; void EM_newline( ); // levels #define CK_LOG_CRAZY 10 // set this to log everything #define CK_LOG_FINEST 9 #define CK_LOG_FINER 8 #define CK_LOG_FINE 7 #define CK_LOG_CONFIG 6 #define CK_LOG_INFO 5 #define CK_LOG_WARNING 4 #define CK_LOG_SEVERE 3 #define CK_LOG_SYSTEM 2 #define CK_LOG_CORE 1 #define CK_LOG_NONE 0 // set this to log nothing void EM_log( int, c_constr, ... ); void EM_setlog( int ); void EM_pushlog(); void EM_poplog(); // actual level extern int g_loglevel; // macro to compare #define DO_LOG(x) ( x <= g_loglevel ) void EM_error( int, c_constr, ... ); void EM_error2( int, c_constr, ... ); void EM_error2b( int, c_constr, ... ); void EM_error3( c_constr, ... ); void EM_impossible( c_constr, ... ); t_CKBOOL EM_reset( c_constr filename, FILE * fd ); void EM_change_file( c_constr filename ); const char * EM_lasterror(); const char * mini( const char * str ); const char * mini_type( const char * str ); #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/chuck_frame.cpp0000644000175000017500000000661410600421722016110 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_frame.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include "chuck_frame.h" using namespace std; //----------------------------------------------------------------------------- // name: Chuck_Frame() // desc: ... //----------------------------------------------------------------------------- Chuck_Frame::Chuck_Frame() { // name name = ""; // ofset curr_offset = 0; // don't know num_access = 0; } //----------------------------------------------------------------------------- // name: alloc_local() // desc: ... //----------------------------------------------------------------------------- Chuck_Local * Chuck_Frame::alloc_local( t_CKUINT size, const string & name, t_CKBOOL is_ref ) { // alloc Chuck_Local * local = new Chuck_Local; // size local->size = size; // the offset local->offset = this->curr_offset; // ref local->is_ref = is_ref; // the next offset this->curr_offset += local->size; // name local->name = name; // push the local this->stack.push_back( local ); return local; } //----------------------------------------------------------------------------- // name: push_scope() // desc: ... //----------------------------------------------------------------------------- void Chuck_Frame::push_scope( ) { stack.push_back( NULL ); } //----------------------------------------------------------------------------- // name: pop_scope() // desc: .... //----------------------------------------------------------------------------- void Chuck_Frame::pop_scope( vector & out ) { // sanity assert( this->stack.size() > 0 ); Chuck_Local * local = NULL; // loop while( this->stack.size() && this->stack.back() ) { // last thing local = stack.back(); // free stack.pop_back(); if( local ) { // offset curr_offset -= local->size; // copy out out.push_back( local ); } } } chuck-1.2.0.8.dfsg/src/chuck_frame.h0000644000175000017500000000532710600421722015555 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_frame.h // desc: ... // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_FRAME_H__ #define __CHUCK_FRAME_H__ #include "chuck_def.h" #include #include //----------------------------------------------------------------------------- // name: struct Chuck_Local // desc: ... //----------------------------------------------------------------------------- struct Chuck_Local { // name std::string name; // the size of the local t_CKUINT size; // is ref t_CKBOOL is_ref; // the offset t_CKUINT offset; // constructor Chuck_Local() { size = 0; is_ref = FALSE; offset = 0; } }; //----------------------------------------------------------------------------- // name: struct Chuck_Frame // desc: ... //----------------------------------------------------------------------------- struct Chuck_Frame { // yes std::string name; // the offset t_CKUINT curr_offset; // not sure t_CKUINT num_access; // offset stack std::vector stack; public: Chuck_Frame(); ~Chuck_Frame() { } public: // push scope void push_scope(); // add local Chuck_Local * alloc_local( t_CKUINT size, const std::string & name, t_CKBOOL is_ref ); // pop scope void pop_scope( std::vector & out ); }; #endif chuck-1.2.0.8.dfsg/src/chuck_globals.cpp0000644000175000017500000000663510600421722016444 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_globals.cpp // desc: global variables slum // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2006 //----------------------------------------------------------------------------- #include "chuck_globals.h" #include "chuck_bbq.h" #include "chuck_errmsg.h" #include "ugen_stk.h" #include "ulib_std.h" #include "hidio_sdl.h" #include #include // current version const char CK_VERSION[] = "1.2.0.8 (dracula)"; // global virtual machine Chuck_VM * g_vm = NULL; // global compiler Chuck_Compiler * g_compiler = NULL; // the shell Chuck_Shell * g_shell = NULL; // global variables t_CKUINT g_sigpipe_mode = 0; // default socket ck_socket g_sock = NULL; // default port t_CKINT g_port = 8888; // real-time watch dog t_CKBOOL g_do_watchdog = FALSE; // countermeasure #ifdef __MACOSX_CORE__ t_CKUINT g_watchdog_countermeasure_priority = 10; #elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__) t_CKUINT g_watchdog_countermeasure_priority = THREAD_PRIORITY_LOWEST; #else t_CKUINT g_watchdog_countermeasure_priority = 0; #endif // watchdog timeout t_CKFLOAT g_watchdog_timeout = 0.5; // thread id for whatever CHUCK_THREAD g_tid_whatever = 0; //----------------------------------------------------------------------------- // name: all_detach() // desc: called during cleanup to close all open file handles //----------------------------------------------------------------------------- extern "C" void all_detach() { // log EM_log( CK_LOG_INFO, "detaching all resources..." ); // push EM_pushlog(); // close stk file handles stk_detach( 0, NULL ); // close midi file handles midirw_detach(); // shutdown kb loop KBHitManager::shutdown(); // shutdown HID HidInManager::cleanup(); // pop EM_poplog(); } //----------------------------------------------------------------------------- // name: signal_pipe() // desc: ... //----------------------------------------------------------------------------- extern "C" void signal_pipe( int sig_num ) { fprintf( stderr, "[chuck]: sigpipe handled - broken pipe (no connection)...\n" ); if( g_sigpipe_mode ) { all_detach(); // exit( 2 ); } } chuck-1.2.0.8.dfsg/src/chuck_globals.h0000644000175000017500000000454210600421722016104 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_globals.h // desc: global variables slum // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2006 //----------------------------------------------------------------------------- #ifndef __CHUCK_GLOBALS_H__ #define __CHUCK_GLOBALS_H__ #include "chuck_def.h" #include "util_network.h" #include "util_thread.h" // forward declarations struct Chuck_VM; struct Chuck_Compiler; class Chuck_Shell; // exports // current version extern const char CK_VERSION[]; // global virtual machine extern Chuck_VM * g_vm; // global compiler extern Chuck_Compiler * g_compiler; // the shell extern Chuck_Shell * g_shell; // global variables extern t_CKUINT g_sigpipe_mode; // global socket extern ck_socket g_sock; // global port extern t_CKINT g_port; // real-time watchdog extern t_CKBOOL g_do_watchdog; // countermeasure priority extern t_CKUINT g_watchdog_countermeasure_priority; // watchdog timeout extern t_CKFLOAT g_watchdog_timeout; // thread id for whatever extern CHUCK_THREAD g_tid_whatever; // global detach extern "C" void all_detach(); // sigpipe function extern "C" void signal_pipe( int sig_num ); #endif chuck-1.2.0.8.dfsg/src/chuck_instr.cpp0000644000175000017500000034224310600421722016156 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_instr.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_type.h" #include "chuck_instr.h" #include "chuck_vm.h" #include "chuck_ugen.h" #include "chuck_bbq.h" #include "chuck_dl.h" #include "chuck_errmsg.h" #include "util_string.h" #include using namespace std; //----------------------------------------------------------------------------- // name: name() // desc: ... //----------------------------------------------------------------------------- const char * Chuck_Instr::name() const { return mini_type( typeid(*this).name() ); } //----------------------------------------------------------------------------- // name: handle_overflow() // desc: stack overflow //----------------------------------------------------------------------------- static void handle_overflow( Chuck_VM_Shred * shred, Chuck_VM * vm ) { // we have a problem fprintf( stderr, "[chuck](VM): Exception StackOverflow in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Add_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) + val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_PreInc_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKINT **& reg_sp = (t_CKINT **&)shred->reg->sp; t_CKINT *& the_sp = (t_CKINT *&)shred->reg->sp; // pointer pop_( reg_sp, 1 ); // increment value (**(reg_sp))++; // value on stack push_( the_sp, **(reg_sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_PostInc_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKINT **& reg_sp = (t_CKINT **&)shred->reg->sp; t_CKINT *& the_sp = (t_CKINT *&)shred->reg->sp; t_CKINT * ptr; // pointer pop_( reg_sp, 1 ); // copy ptr = *reg_sp; // value on stack push_( the_sp, **(reg_sp) ); // increment value (*(ptr))++; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_PreDec_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKINT **& reg_sp = (t_CKINT **&)shred->reg->sp; t_CKINT *& the_sp = (t_CKINT *&)shred->reg->sp; // pointer pop_( reg_sp, 1 ); // decrement value (**(reg_sp))--; // value on stack push_( the_sp, **(reg_sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_PostDec_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKINT **& reg_sp = (t_CKINT **&)shred->reg->sp; t_CKINT *& the_sp = (t_CKINT *&)shred->reg->sp; t_CKINT * ptr; // pointer pop_( reg_sp, 1 ); // copy ptr = *reg_sp; // value on stack push_( the_sp, **(reg_sp) ); // decrement value (*(ptr))--; } //----------------------------------------------------------------------------- // name: class Chuck_Instr_Dec_int_Addr // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dec_int_Addr::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // decrement value (*((t_CKINT *)(m_val)))--; } //----------------------------------------------------------------------------- // name: exexute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Complement_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; (*(sp-1)) = ~(*(sp-1)); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) % val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) % val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) - val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_int_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) - val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Times_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) * val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) / val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_int_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) / val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Add_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) + val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) - val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_double_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) - val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Times_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) * val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) / val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_double_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) / val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, ::fmod( val_(sp), val_(sp+1) ) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, ::fmod( val_(sp+1), val_(sp) ) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Add_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) += val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) %= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) -= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Times_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) *= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_int_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) /= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Add_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT temp; t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); // assign temp = **(t_CKFLOAT **)(sp+sz_FLOAT) += val_((t_CKFLOAT *&)sp); // push result push_( (t_CKFLOAT *&)sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Minus_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT temp; t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); // assign temp = **(t_CKFLOAT **)(sp+sz_FLOAT) -= val_((t_CKFLOAT *&)sp); // push result push_( (t_CKFLOAT *&)sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Times_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT temp; t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); // assign temp = **(t_CKFLOAT **)(sp+sz_FLOAT) *= val_((t_CKFLOAT *&)sp); // push result push_( (t_CKFLOAT *&)sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Divide_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT temp; t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); // assign temp = **(t_CKFLOAT **)(sp+sz_FLOAT) /= val_((t_CKFLOAT *&)sp); // push result push_( (t_CKFLOAT *&)sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mod_double_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT temp; t_CKBYTE *& sp = (t_CKBYTE *&)shred->reg->sp; // pop value + pointer pop_( sp, sz_FLOAT + sz_UINT ); // assign temp = ::fmod( **(t_CKFLOAT **)(sp+sz_FLOAT), val_((t_CKFLOAT *&)sp) ); **(t_CKFLOAT **)(sp+sz_FLOAT) = temp; // push result push_( (t_CKFLOAT *&)sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: string + string //----------------------------------------------------------------------------- void Chuck_Instr_Add_string::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; Chuck_String * rhs = NULL; Chuck_String * result = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // left lhs = (Chuck_String *)(*(reg_sp)); // right rhs = (Chuck_String *)(*(reg_sp+1)); // make sure no null if( !rhs || !lhs ) goto null_pointer; // make new string result = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // concat result->str = lhs->str + rhs->str; // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(result) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (string + string) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: add assign string //----------------------------------------------------------------------------- void Chuck_Instr_Add_string_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; Chuck_String ** rhs_ptr = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // the previous reference rhs_ptr = (Chuck_String **)(*(reg_sp+1)); // copy popped value into memory lhs = (Chuck_String *)(*(reg_sp)); // make sure no null if( !(*rhs_ptr) ) goto null_pointer; // concat (*rhs_ptr)->str += lhs->str; // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(*rhs_ptr) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (string + string) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: string + int //----------------------------------------------------------------------------- void Chuck_Instr_Add_string_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; t_CKINT rhs = 0; Chuck_String * result = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // left lhs = (Chuck_String *)(*(reg_sp)); // right rhs = (*(t_CKINT *)(reg_sp+1)); // make sure no null if( !lhs ) goto null_pointer; // make new string result = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // concat result->str = lhs->str + ::itoa(rhs); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(result) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (string + int) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: string + float //----------------------------------------------------------------------------- void Chuck_Instr_Add_string_float::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; t_CKFLOAT rhs = 0; Chuck_String * result = NULL; // pop word from reg stack pop_( reg_sp, 3 ); // left lhs = (Chuck_String *)(*(reg_sp)); // right rhs = (*(t_CKFLOAT *)(reg_sp+1)); // make sure no null if( !lhs ) goto null_pointer; // make new string result = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // concat result->str = lhs->str + ::ftoa(rhs, 4); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(result) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (string + float) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: int + string //----------------------------------------------------------------------------- void Chuck_Instr_Add_int_string::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKINT lhs = 0; Chuck_String * rhs = NULL; Chuck_String * result = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // left lhs = (*(t_CKINT *)(reg_sp)); // right rhs = (Chuck_String *)(*(reg_sp+1)); // make sure no null if( !rhs ) goto null_pointer; // make new string result = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // concat result->str = ::itoa(lhs) + rhs->str; // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(result) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (int + string) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: float + string //----------------------------------------------------------------------------- void Chuck_Instr_Add_float_string::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKFLOAT lhs = 0; Chuck_String * rhs = NULL; Chuck_String * result = NULL; // pop word from reg stack pop_( reg_sp, 3 ); // left (2 word) lhs = (*(t_CKFLOAT *)(reg_sp)); // right rhs = (Chuck_String *)(*(reg_sp+2)); // make sure no null if( !rhs ) goto null_pointer; // make new string result = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // concat result->str = ::ftoa(lhs, 4) + rhs->str; // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(result) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (int + string) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: add assign int string //----------------------------------------------------------------------------- void Chuck_Instr_Add_int_string_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKINT lhs = 0; Chuck_String ** rhs_ptr = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // the previous reference rhs_ptr = (Chuck_String **)(*(reg_sp+1)); // copy popped value into memory lhs = (*(t_CKINT *)(reg_sp)); // make sure no null if( !(*rhs_ptr) ) goto null_pointer; // concat (*rhs_ptr)->str += ::itoa(lhs); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(*rhs_ptr) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: () in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: add assign float string //----------------------------------------------------------------------------- void Chuck_Instr_Add_float_string_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKFLOAT lhs = 0; Chuck_String ** rhs_ptr = NULL; // pop word from reg stack pop_( reg_sp, 3 ); // the previous reference rhs_ptr = (Chuck_String **)(*(reg_sp+2)); // copy popped value into memory lhs = (*(t_CKFLOAT *)(reg_sp)); // make sure no null if( !(*rhs_ptr) ) goto null_pointer; // concat (*rhs_ptr)->str += ::ftoa(lhs, 4); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)(*rhs_ptr) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (string + string) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Imm::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // push val into reg stack push_( reg_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Imm2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& reg_sp = (t_CKFLOAT *&)shred->reg->sp; // push val into reg stack push_( reg_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Dup_Last::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // dup val into reg stack push_( reg_sp, *(reg_sp-1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Dup_Last2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& reg_sp = (t_CKFLOAT *&)shred->reg->sp; // dup val into reg stack push_( reg_sp, *(reg_sp-1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Now::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKTIME *& reg_sp = (t_CKTIME *&)shred->reg->sp; // push val into reg stack push_( reg_sp, shred->now ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Me::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // push val into reg stack push_( reg_sp, (t_CKUINT)shred ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_This::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; // push val into reg stack push_( reg_sp, *(mem_sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Start::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKTIME *& reg_sp = (t_CKTIME *&)shred->reg->sp; // push val into reg stack push_( reg_sp, shred->start ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Maybe::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& reg_sp = (t_CKINT *&)shred->reg->sp; // push val into reg stack float num = (float)rand() / (float)RAND_MAX; push_( reg_sp, num > .5 ); } //----------------------------------------------------------------------------- // name: execute() // desc: push the value pointed to by m_val onto register stack //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Deref::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { if( m_size == 4 ) // ISSUE: 64-bit { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; push_( reg_sp, *((t_CKUINT *)m_val) ); } else { t_CKFLOAT *& reg_sp = (t_CKFLOAT *&)shred->reg->sp; push_( reg_sp, *((t_CKFLOAT *)m_val) ); } } //----------------------------------------------------------------------------- // name: execute() // desc: push value from memory stack to register stack //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Mem::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)(base?shred->base_ref->stack:shred->mem->sp); t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // push mem stack content into reg stack push_( reg_sp, *((t_CKUINT *)(mem_sp + m_val)) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Mem2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)(base?shred->base_ref->stack:shred->mem->sp); t_CKFLOAT *& reg_sp = (t_CKFLOAT *&)shred->reg->sp; // push mem stack content into reg stack push_( reg_sp, *((t_CKFLOAT *)(mem_sp + m_val)) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Push_Mem_Addr::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)(base?shred->base_ref->stack:shred->mem->sp); t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // push mem stack addr into reg stack push_( reg_sp, (t_CKUINT)(mem_sp + m_val) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Pop_Mem::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, 2 ); // copy popped value into mem stack *((t_CKUINT *)(mem_sp + *(reg_sp+1) )) = *reg_sp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Pop_Word::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, 1 ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Pop_Word2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& reg_sp = (t_CKFLOAT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, 1 ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Reg_Pop_Word3::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Set_Imm::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT * mem_sp = (t_CKUINT *)(shred->mem->sp + m_offset); // set *(mem_sp) = m_val; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Set_Imm2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT * mem_sp = (t_CKFLOAT *)(shred->mem->sp + m_offset); // set *(mem_sp) = m_val; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Push_Imm::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; // pop word from reg stack push_( mem_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Push_Imm2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& mem_sp = (t_CKFLOAT *&)shred->mem->sp; // pop word from reg stack push_( mem_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Pop_Word::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; // pop word from reg stack pop_( mem_sp, 1 ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Pop_Word2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& mem_sp = (t_CKFLOAT *&)shred->mem->sp; // pop word from reg stack pop_( mem_sp, 1 ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Mem_Pop_Word3::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; // pop word from reg stack pop_( mem_sp, m_val ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Lt_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) < val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Gt_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) > val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Le_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) <= val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Ge_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) >= val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Eq_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) == val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Neq_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) != val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Not_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; (*(sp-1)) = !(*(sp-1)); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Negate_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; (*(sp-1)) = -(*(sp-1)); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Negate_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; (*(sp-1)) = -(*(sp-1)); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Lt_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) < val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Gt_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) > val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Le_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) <= val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Ge_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) >= val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Eq_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) == val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Branch_Neq_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; pop_( sp, 2 ); if( val_(sp) != val_(sp+1) ) shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_And::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) & val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Or::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) | val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Xor::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) ^ val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Right::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) >> val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Right_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) >> val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Left::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) << val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Left_Reverse::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp+1) << val_(sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_And_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) &= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Or_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) |= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Xor_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) ^= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Right_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) >>= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Binary_Shift_Left_Assign::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT temp, *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); temp = **(t_CKINT **)(sp+1) <<= val_(sp); push_( sp, temp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Lt_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) < val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Gt_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) > val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Le_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) <= val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Ge_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) >= val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Eq_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) == val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Neq_int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) != val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Lt_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) < val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Gt_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) > val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Le_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) <= val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Ge_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) >= val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Eq_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) == val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Neq_double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKUINT *& sp_uint = (t_CKUINT *&)sp; pop_( sp, 2 ); push_( sp_uint, val_(sp) != val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_And::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) && val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Or::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); push_( sp, val_(sp) || val_(sp+1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Goto::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { shred->next_pc = m_jmp; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Nop::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // no op } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_EOC::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // end the shred shred->is_done = TRUE; shred->is_running = FALSE; } //----------------------------------------------------------------------------- // name: execute() // desc: alloc local //----------------------------------------------------------------------------- void Chuck_Instr_Alloc_Word::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // zero out the memory stack *( (t_CKUINT *)(mem_sp + m_val) ) = 0; // push addr onto operand stack push_( reg_sp, (t_CKUINT)(mem_sp + m_val) ); } //----------------------------------------------------------------------------- // name: execute() // desc: alloc local //----------------------------------------------------------------------------- void Chuck_Instr_Alloc_Word2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // zero out the memory stack *( (t_CKFLOAT *)(mem_sp + m_val) ) = 0.0; // push addr onto operand stack push_( reg_sp, (t_CKUINT)(mem_sp + m_val) ); } //----------------------------------------------------------------------------- // name: execute() // desc: alloc member //----------------------------------------------------------------------------- void Chuck_Instr_Alloc_Member_Word::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // get the object Chuck_Object * obj = (Chuck_Object *)*(mem_sp); // zero out the memory stack *( (t_CKUINT *)(obj->data + m_val) ) = 0; // push addr onto operand stack push_( reg_sp, (t_CKUINT)(obj->data + m_val) ); } //----------------------------------------------------------------------------- // name: execute() // desc: alloc member //----------------------------------------------------------------------------- void Chuck_Instr_Alloc_Member_Word2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // get the object Chuck_Object * obj = (Chuck_Object *)*(mem_sp); // zero out the memory stack *( (t_CKFLOAT *)(obj->data + m_val) ) = 0.0; // push addr onto operand stack push_( reg_sp, (t_CKUINT)(obj->data + m_val) ); } static Chuck_Instr_Func_Call g_func_call; static Chuck_Instr_Func_Call_Member g_func_call_member( 0 ); //----------------------------------------------------------------------------- // name: call_pre_constructor() // desc: ... //----------------------------------------------------------------------------- inline void call_pre_constructor( Chuck_VM * vm, Chuck_VM_Shred * shred, Chuck_VM_Code * pre_ctor, t_CKUINT stack_offset ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // sanity assert( pre_ctor != NULL ); // first duplicate the top of the stack, which should be object pointer push_( reg_sp, *(reg_sp-1) ); // push the pre constructor push_( reg_sp, (t_CKUINT)pre_ctor ); // push the stack offset push_( reg_sp, stack_offset ); // call the function if( pre_ctor->native_func != 0 ) g_func_call_member.execute( vm, shred ); else g_func_call.execute( vm, shred ); } //----------------------------------------------------------------------------- // name: execute() // desc: object pre construct //----------------------------------------------------------------------------- void Chuck_Instr_Pre_Constructor::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { call_pre_constructor( vm, shred, pre_ctor, stack_offset ); } //----------------------------------------------------------------------------- // name: instantiate_object() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL initialize_object( Chuck_Object * object, Chuck_Type * type ) { // sanity assert( type != NULL ); assert( type->info != NULL ); // allocate virtual table object->vtable = new Chuck_VTable; if( !object->vtable ) goto out_of_memory; // copy the object's virtual table object->vtable->funcs = type->info->obj_v_table.funcs; // set the type reference // TODO: reference count object->type_ref = type; object->type_ref->add_ref(); // get the size object->size = type->obj_size; // allocate memory if( object->size ) { // check to ensure enough memory object->data = new t_CKBYTE[object->size]; if( !object->data ) goto out_of_memory; // zero it out memset( object->data, 0, object->size ); } else object->data = NULL; // special if( type->ugen_info ) { // ugen Chuck_UGen * ugen = (Chuck_UGen *)object; if( type->ugen_info->tick ) ugen->tick = type->ugen_info->tick; if( type->ugen_info->pmsg ) ugen->pmsg = type->ugen_info->pmsg; // allocate multi chan ugen->alloc_multi_chan( type->ugen_info->num_ins, type->ugen_info->num_outs ); // allocate the channels for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) { // allocate ugen for each Chuck_Object * obj = instantiate_and_initialize_object( &t_ugen, ugen->shred ); // cast to ugen ugen->m_multi_chan[i] = (Chuck_UGen *)obj; // additional reference count ugen->m_multi_chan[i]->add_ref(); // owner ugen->m_multi_chan[i]->owner = ugen; // ref count ugen->add_ref(); } } return TRUE; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while instantiating object '%s'\n", type->c_name() ); // delete if( object ) SAFE_DELETE( object->vtable ); // return FALSE return FALSE; } //----------------------------------------------------------------------------- // name: instantiate_and_initialize_object() // desc: ... //----------------------------------------------------------------------------- Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Shred * shred ) { Chuck_Object * object = NULL; // sanity assert( type != NULL ); assert( type->info != NULL ); // allocate the VM object if( !type->ugen_info ) { // check type TODO: make this faster if( isa( type, &t_event ) ) object = new Chuck_Event; else if( isa( type, &t_string ) ) object = new Chuck_String; else object = new Chuck_Object; } else { // make ugen Chuck_UGen * ugen; object = ugen = new Chuck_UGen; if( shred ) { ugen->shred = shred; shred->add( ugen ); } } // check to see enough memory if( !object ) goto out_of_memory; // initialize if( !initialize_object( object, type ) ) goto error; return object; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while instantiating object '%s'\n", type->c_name() ); error: // delete SAFE_DELETE( object ); // return NULL return NULL; } //----------------------------------------------------------------------------- // name: instantiate_object() // desc: ... //----------------------------------------------------------------------------- inline void instantiate_object( Chuck_VM * vm, Chuck_VM_Shred * shred, Chuck_Type * type ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // allocate the VM object Chuck_Object * object = instantiate_and_initialize_object( type, shred ); if( !object ) goto error; // push the pointer on the operand stack push_( reg_sp, (t_CKUINT)object ); // call preconstructor // call_pre_constructor( vm, shred, object, type, stack_offset ); return; error: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: instantiate object //----------------------------------------------------------------------------- void Chuck_Instr_Instantiate_Object::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { instantiate_object( vm, shred, this->type ); } //----------------------------------------------------------------------------- // name: params() // desc: ... //----------------------------------------------------------------------------- const char * Chuck_Instr_Instantiate_Object::params() const { static char buffer[256]; sprintf( buffer, "%s", this->type->c_name() ); return buffer; } //----------------------------------------------------------------------------- // name: execute() // desc: object pre construct top //----------------------------------------------------------------------------- void Chuck_Instr_Pre_Ctor_Array_Top::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // see if we are done with all elements in the array if( *(reg_sp-2) >= *(reg_sp-1) ) shred->next_pc = m_val; else { // instantiate instantiate_object( vm, shred, type ); } } //----------------------------------------------------------------------------- // name: execute() // desc: object pre construct bottom //----------------------------------------------------------------------------- void Chuck_Instr_Pre_Ctor_Array_Bottom::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop the object pop_( reg_sp, 1 ); // cast the object Chuck_Object * obj = (Chuck_Object *)(*(reg_sp)); // assign object t_CKUINT * array = (t_CKUINT *)(*(reg_sp-3)); // get the object pointer Chuck_Object ** dest = (Chuck_Object **)(array[*(reg_sp-2)]); // copy *dest = obj; // ref count obj->add_ref(); // increment the index (*(reg_sp-2))++; //= (*(reg_sp-2)) + 1; // goto top shred->next_pc = m_val; } //----------------------------------------------------------------------------- // name: execute() // desc: object pre construct post //----------------------------------------------------------------------------- void Chuck_Instr_Pre_Ctor_Array_Post::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop the array, index, and size pop_( reg_sp, 3 ); } //----------------------------------------------------------------------------- // name: execute() // desc: assign primitive (word) //----------------------------------------------------------------------------- void Chuck_Instr_Assign_Primitive::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, 2 ); // copy popped value into mem stack *((t_CKUINT *)(*(reg_sp+1))) = *reg_sp; push_( reg_sp, *reg_sp ); } //----------------------------------------------------------------------------- // name: execute() // desc: assign primitive (2 word) //----------------------------------------------------------------------------- void Chuck_Instr_Assign_Primitive2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( reg_sp, 3 ); // copy popped value into mem stack *( (t_CKFLOAT *)(*(reg_sp+2)) ) = *(t_CKFLOAT *)reg_sp; t_CKFLOAT *& sp_double = (t_CKFLOAT *&)reg_sp; push_( sp_double, *sp_double ); } //----------------------------------------------------------------------------- // name: execute() // desc: assign object with reference counting and releasing previous reference //----------------------------------------------------------------------------- void Chuck_Instr_Assign_Object::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_VM_Object ** obj = NULL, * done = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // the previous reference obj = (Chuck_VM_Object **)(*(reg_sp+1)); // save the reference (release should come after, in case same object) done = *obj; // copy popped value into memory *obj = (Chuck_VM_Object *)(*(reg_sp)); // add reference if( *obj ) (*obj)->add_ref(); // release if( done ) done->release(); // copy // memcpy( (void *)*(reg_sp+1), *obj, sizeof(t_CKUINT) ); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)*obj ); } //----------------------------------------------------------------------------- // name: execute() // desc: assign string //----------------------------------------------------------------------------- void Chuck_Instr_Assign_String::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; Chuck_String ** rhs_ptr = NULL; // pop word from reg stack pop_( reg_sp, 2 ); // the previous reference rhs_ptr = (Chuck_String **)(*(reg_sp+1)); // copy popped value into memory lhs = (Chuck_String *)(*(reg_sp)); // release any previous reference if( *rhs_ptr ) { if( lhs ) (*rhs_ptr)->str = lhs->str; else { // release reference (*rhs_ptr)->release(); (*rhs_ptr) = NULL; } } else { // if left is not null, yes if( lhs != NULL ) { (*rhs_ptr) = (Chuck_String *)instantiate_and_initialize_object( &t_string, shred ); // add ref (*rhs_ptr)->add_ref(); (*rhs_ptr)->str = lhs->str; } //EM_error2( 0, "internal error: somehow the type checker has allowed NULL strings" ); //EM_error2( 0, "we are sorry for the inconvenience but..." ); //EM_error2( 0, "we have to crash now. Thanks." ); //assert( FALSE ); } // copy // memcpy( (void *)*(reg_sp+1), *obj, sizeof(t_CKUINT) ); // push the reference value to reg stack push_( reg_sp, (t_CKUINT)*rhs_ptr ); } //----------------------------------------------------------------------------- // name: execute() // desc: release one reference on object //----------------------------------------------------------------------------- void Chuck_Instr_Chuck_Release_Object::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE *& mem_sp = (t_CKBYTE *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_VM_Object * obj = NULL; // pop word from reg stack pop_( reg_sp, 1 ); // copy popped value into mem stack obj = *( (Chuck_VM_Object **)(mem_sp + *(reg_sp)) ); // release obj->release(); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Func_To_Code::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // get func Chuck_Func * func = (Chuck_Func *)*(reg_sp-1); // make sure assert( func != NULL ); // code *(reg_sp-1) = (t_CKUINT)func->code; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Func_Call::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop word pop_( reg_sp, 2 ); // get the function to be called as code Chuck_VM_Code * func = (Chuck_VM_Code *)*reg_sp; // get the local stack depth - caller local variables t_CKUINT local_depth = *(reg_sp+1); // convert to number of 4-byte words, extra partial word counts as additional word local_depth = ( local_depth >> 2 ) + ( local_depth & 0x3 ? 1 : 0 ); // get the stack depth of the callee function args t_CKUINT stack_depth = ( func->stack_depth >> 2 ) + ( func->stack_depth & 0x3 ? 1 : 0 ); // get the previous stack depth - caller function args t_CKUINT prev_stack = ( *(mem_sp-1) >> 2 ) + ( *(mem_sp-1) & 0x3 ? 1 : 0 ); // jump the sp mem_sp += prev_stack + local_depth; // push the prev stack push_( mem_sp, prev_stack + local_depth ); // push the current function push_( mem_sp, (t_CKUINT)shred->code ); // push the pc push_( mem_sp, (t_CKUINT)(shred->pc + 1) ); // push the stack depth push_( mem_sp, stack_depth ); // set the pc to 0 shred->next_pc = 0; // set the code shred->code = func; // set the instruction to the function instruction shred->instr = func->instr; // if there are arguments to be passed if( stack_depth ) { // pop the arguments, by number of words pop_( reg_sp, stack_depth ); // make copies t_CKUINT * mem_sp2 = (t_CKUINT *)mem_sp; t_CKUINT * reg_sp2 = (t_CKUINT *)reg_sp; // need this if( func->need_this ) { // copy this from end of arguments to the front *mem_sp2++ = *(reg_sp2 + stack_depth - 1); // one less word to copy stack_depth--; } // push the arguments for( t_CKUINT i = 0; i < stack_depth; i++ ) *mem_sp2++ = *reg_sp2++; } // detect overflow/underflow if( overflow_( shred->mem ) ) goto error_overflow; return; error_overflow: handle_overflow( shred, vm ); } //----------------------------------------------------------------------------- // name: execute() // desc: imported member function call with return //----------------------------------------------------------------------------- void Chuck_Instr_Func_Call_Member::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_DL_Return retval; // pop word pop_( reg_sp, 2 ); // get the function to be called as code Chuck_VM_Code * func = (Chuck_VM_Code *)*reg_sp; // get the function to be called // MOVED TO BELOW: f_mfun f = (f_mfun)func->native_func; // get the local stack depth - caller local variables t_CKUINT local_depth = *(reg_sp+1); // convert to number of 4-byte words, extra partial word counts as additional word local_depth = ( local_depth >> 2 ) + ( local_depth & 0x3 ? 1 : 0 ); // get the stack depth of the callee function args t_CKUINT stack_depth = ( func->stack_depth >> 2 ) + ( func->stack_depth & 0x3 ? 1 : 0 ); // UNUSED: get the previous stack depth - caller function args // UNUSED: t_CKUINT prev_stack = ( *(mem_sp-1) >> 2 ) + ( *(mem_sp-1) & 0x3 ? 1 : 0 ); // the amount to push in 4-byte words t_CKUINT push = local_depth; // push the mem stack passed the current function variables and arguments mem_sp += push; // pass args if( stack_depth ) { // pop the arguments for pass to callee function reg_sp -= stack_depth; // make copies t_CKUINT * reg_sp2 = reg_sp; t_CKUINT * mem_sp2 = mem_sp; // need this if( func->need_this ) { // copy this from end of arguments to the front *mem_sp2++ = *(reg_sp2 + stack_depth - 1); // one less word to copy stack_depth--; } // copy to args for( t_CKUINT i = 0; i < stack_depth; i++ ) *mem_sp2++ = *reg_sp2++; } // detect overflow/underflow if( overflow_( shred->mem ) ) goto error_overflow; // check the type if( func->native_func_type == Chuck_VM_Code::NATIVE_CTOR ) { // cast to right type f_ctor f = (f_ctor)func->native_func; // call f( (Chuck_Object *)(*mem_sp), mem_sp + 1, shred ); } else { // cast to right type f_mfun f = (f_mfun)func->native_func; // call the function f( (Chuck_Object *)(*mem_sp), mem_sp + 1, &retval, shred ); } // pop (TODO: check if this is right) mem_sp -= push; // push the return if( m_val == 4 ) // ISSUE: 64-bit { // push the return args push_( reg_sp, retval.v_uint ); } else if( m_val == 8 ) // ISSUE: 64-bit { // push the return args t_CKFLOAT *& sp_double = (t_CKFLOAT *&)reg_sp; push_( sp_double, retval.v_float ); } else if( m_val == 0 ) { } else assert( FALSE ); return; error_overflow: handle_overflow( shred, vm ); } //----------------------------------------------------------------------------- // name: execute() // desc: imported static function call with return //----------------------------------------------------------------------------- void Chuck_Instr_Func_Call_Static::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; Chuck_DL_Return retval; // pop word pop_( reg_sp, 2 ); // get the function to be called as code Chuck_VM_Code * func = (Chuck_VM_Code *)*reg_sp; // get the function to be called f_sfun f = (f_sfun)func->native_func; // get the local stack depth - caller local variables t_CKUINT local_depth = *(reg_sp+1); // convert to number of 4-byte words, extra partial word counts as additional word local_depth = ( local_depth >> 2 ) + ( local_depth & 0x3 ? 1 : 0 ); // get the stack depth of the callee function args t_CKUINT stack_depth = ( func->stack_depth >> 2 ) + ( func->stack_depth & 0x3 ? 1 : 0 ); // UNUSED: get the previous stack depth - caller function args // UNUSED: t_CKUINT prev_stack = ( *(mem_sp-1) >> 2 ) + ( *(mem_sp-1) & 0x3 ? 1 : 0 ); // the amount to push in 4-byte words t_CKUINT push = local_depth; // push the mem stack passed the current function variables and arguments mem_sp += push; // pass args if( stack_depth ) { // pop the arguments for pass to callee function reg_sp -= stack_depth; // make copies t_CKUINT * reg_sp2 = reg_sp; t_CKUINT * mem_sp2 = mem_sp; // need this if( func->need_this ) { // copy this from end of arguments to the front *mem_sp2++ = *(reg_sp2 + stack_depth - 1); // advance reg pointer reg_sp2++; // one less word to copy stack_depth--; } // copy to args for( t_CKUINT i = 0; i < stack_depth; i++ ) *mem_sp2++ = *reg_sp2++; } // detect overflow/underflow if( overflow_( shred->mem ) ) goto error_overflow; // call the function f( mem_sp, &retval, shred ); mem_sp -= push; // push the return if( m_val == 4 ) // ISSUE: 64-bit { // push the return args push_( reg_sp, retval.v_uint ); } else if( m_val == 8 ) // ISSUE: 64-bit { // push the return args t_CKFLOAT *& sp_double = (t_CKFLOAT *&)reg_sp; push_( sp_double, retval.v_float ); } else if( m_val == 0 ) { } else assert( FALSE ); return; error_overflow: handle_overflow( shred, vm ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Func_Return::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& mem_sp = (t_CKUINT *&)shred->mem->sp; // UNUSED: t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // pop pc pop_( mem_sp, 2 ); shred->next_pc = *mem_sp; // pop the code pop_( mem_sp, 1 ); Chuck_VM_Code * func = (Chuck_VM_Code *)*mem_sp; // pop the prev_stack pop_( mem_sp, 1 ); // jump the prev stack mem_sp -= *(mem_sp); // set the shred shred->code = func; shred->instr = func->instr; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Spork::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; t_CKUINT this_ptr = 0; // pop the stack pop_( reg_sp, 1 ); // get the code Chuck_VM_Code * code = *(Chuck_VM_Code **)reg_sp; // spork it Chuck_VM_Shred * sh = vm->spork( code, shred ); // pop the stack pop_( reg_sp, 1 ); // get the func Chuck_Func * func = (Chuck_Func *)(*reg_sp); // need this? if( func->is_member ) { // pop the stack pop_( reg_sp, 1 ); // get this this_ptr = *reg_sp; } // copy args if( m_val ) { pop_( shred->reg->sp, m_val ); memcpy( sh->reg->sp, shred->reg->sp, m_val ); sh->reg->sp += m_val; } // copy this, if need if( func->is_member ) { push_( (t_CKUINT*&)sh->reg->sp, this_ptr ); } // copy func push_( (t_CKUINT*&)sh->reg->sp, (t_CKUINT)func ); // push the stack push_( reg_sp, (t_CKUINT)sh ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Time_Advance::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKTIME *& sp = (t_CKTIME *&)shred->reg->sp; // pop word from reg stack pop_( sp, 1 ); if( *sp < shred->now ) { // we have a problem fprintf( stderr, "[chuck](VM): DestTimeNegativeException: '%.6f' in shred[id=%d:%s], PC=[%d]\n", *sp, shred->xid, shred->name.c_str(), shred->pc ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; return; } // shredule the shred vm->shreduler()->shredule( shred, *sp ); // suspend shred->is_running = FALSE; // track time advance CK_TRACK( Chuck_Stats::instance()->advance_time( shred, *sp ) ); push_( sp, *sp ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Event_Wait::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // pop word from reg stack pop_( sp, 1 ); Chuck_Event * event = (Chuck_Event *)(*sp); // check for null if( !event ) goto null_pointer; // wait event->wait( shred, vm ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (null Event wait) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: Chuck_Instr_Array_Init() // desc: ... //----------------------------------------------------------------------------- Chuck_Instr_Array_Init::Chuck_Instr_Array_Init( Chuck_Type * t , t_CKINT length ) { // set m_length = length; // copy m_type_ref = t; // remember // m_type_ref->add_ref(); // type m_param_str = new char[64]; // obj m_is_obj = isobj( m_type_ref ); const char * str = m_type_ref->c_name(); t_CKUINT len = strlen( str ); // copy if( len < 48 ) strcpy( m_param_str, str ); else { strncpy( m_param_str, str, 48 ); strcpy( m_param_str + 48, "..." ); } // append length char buffer[16]; sprintf( buffer, "[%ld]", m_length ); strcat( m_param_str, buffer ); } //----------------------------------------------------------------------------- // name: ~Chuck_Instr_Array_Init() // desc: ... //----------------------------------------------------------------------------- Chuck_Instr_Array_Init::~Chuck_Instr_Array_Init() { // delete delete [] m_param_str; m_param_str = NULL; // release //m_type_ref->release(); m_type_ref = NULL; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Array_Init::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // allocate the array if( m_type_ref->size == 4 ) // ISSUE: 64-bit { // pop the values pop_( reg_sp, m_length ); // instantiate array Chuck_Array4 * array = new Chuck_Array4( m_is_obj, m_length ); // problem if( !array ) goto out_of_memory; // initialize object initialize_object( array, &t_array ); // fill array for( t_CKINT i = 0; i < m_length; i++ ) array->set( i, *(reg_sp + i) ); // set size array->m_size = m_length; // push the pointer push_( reg_sp, (t_CKUINT)array ); } else if( m_type_ref->size == 8 ) // ISSUE: 64-bit { // pop the values pop_( reg_sp, 2 * m_length ); // instantiate array Chuck_Array8 * array = new Chuck_Array8( m_length ); // problem if( !array ) goto out_of_memory; // fill array t_CKFLOAT * sp = (t_CKFLOAT *)reg_sp; // intialize object initialize_object( array, &t_array ); // fill array for( t_CKINT i = 0; i < m_length; i++ ) array->set( i, *(sp + i) ); // set size array->m_size = m_length; // push the pointer push_( reg_sp, (t_CKUINT)array ); } else assert( FALSE ); return; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while initializing arrays\n" ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: Chuck_Instr_Array_Alloc() // desc: ... //----------------------------------------------------------------------------- Chuck_Instr_Array_Alloc::Chuck_Instr_Array_Alloc( t_CKUINT depth, Chuck_Type * t, t_CKUINT offset, t_CKBOOL is_ref ) { // set m_depth = depth; // copy m_type_ref = t; // remember // m_type_ref->add_ref(); // type m_param_str = new char[64]; // obj m_is_obj = isobj( m_type_ref ); // offset for pre constructor m_stack_offset = offset; // is object ref m_is_ref = is_ref; const char * str = m_type_ref->c_name(); t_CKUINT len = strlen( str ); // copy if( len < 64 ) strcpy( m_param_str, str ); else { strncpy( m_param_str, str, 60 ); strcpy( m_param_str + 60, "..." ); } } //----------------------------------------------------------------------------- // name: ~Chuck_Instr_Array_Alloc() // desc: ... //----------------------------------------------------------------------------- Chuck_Instr_Array_Alloc::~Chuck_Instr_Array_Alloc() { // delete delete [] m_param_str; m_param_str = NULL; // release //m_type_ref->release(); m_type_ref = NULL; } //----------------------------------------------------------------------------- // name: do_alloc_array() // desc: ... //----------------------------------------------------------------------------- Chuck_Object * do_alloc_array( t_CKINT * capacity, const t_CKINT * top, t_CKUINT size, t_CKBOOL is_obj, t_CKUINT * objs, t_CKINT & index ) { // not top level Chuck_Array4 * base = NULL; Chuck_Object * next = NULL; t_CKINT i = 0; // capacity if( *capacity < 0 ) goto negative_array_size; // see if top level if( capacity >= top ) { // check size if( size == 4 ) // ISSUE: 64-bit { Chuck_Array4 * base = new Chuck_Array4( is_obj, *capacity ); if( !base ) goto out_of_memory; // if object if( is_obj && objs ) { // loop for( i = 0; i < *capacity; i++ ) { // add to array for later allocation objs[index++] = base->addr( i ); } } // initialize object initialize_object( base, &t_array ); return base; } else { Chuck_Array8 * base = new Chuck_Array8( *capacity ); if( !base ) goto out_of_memory; // initialize object initialize_object( base, &t_array ); return base; } // shouldn't get here assert( FALSE ); } // not top level base = new Chuck_Array4( TRUE, *capacity ); if( !base ) goto out_of_memory; // allocate the next level for( i = 0; i < base->capacity(); i++ ) { // the next next = do_alloc_array( capacity+1, top, size, is_obj, objs, index ); // error if NULL if( !next ) goto error; // set that, with ref count base->set( i, (t_CKUINT)next ); } // initialize object initialize_object( base, &t_array ); return base; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while allocating arrays...\n" ); goto error; negative_array_size: // we have a problem fprintf( stderr, "[chuck](VM): NegativeArraySize: while allocating arrays...\n" ); goto error; error: // base shouldn't have been ref counted SAFE_DELETE( base ); return NULL; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Array_Alloc::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; // ref t_CKUINT ref = 0; // the total number of objects to allocate t_CKUINT num_obj = 0; // the index to pass to the arrays t_CKINT index = 0; // number t_CKFLOAT num = 1.0; // if need instantiation if( m_is_obj && !m_is_ref ) { t_CKINT * curr = (t_CKINT *)(reg_sp - m_depth); t_CKINT * top = (t_CKINT *)(reg_sp - 1); num_obj = 1; num = 1.0; // product of all dims while( curr <= top ) { num_obj *= *(curr); // overflow num *= (t_CKFLOAT)(*(curr)); if( num > (t_CKFLOAT)INT_MAX ) goto overflow; curr++; } // check to see if we need to allocate if( num > shred->obj_array_size ) { SAFE_DELETE( shred->obj_array ); shred->obj_array_size = 0; shred->obj_array = new t_CKUINT[num_obj]; if( !shred->obj_array ) goto out_of_memory; shred->obj_array_size = num_obj; } } // recursively allocate ref = (t_CKUINT)do_alloc_array( (t_CKINT *)(reg_sp - m_depth), (t_CKINT *)(reg_sp - 1), m_type_ref->size, m_is_obj, shred->obj_array, index ); // pop the indices - this protects the contents of the stack // do_alloc_array writes stuff to the stack pop_( reg_sp, m_depth ); // make sure assert( index == (t_CKINT)num_obj ); // problem if( !ref ) goto error; // push array push_( reg_sp, ref ); // if need to instantiate if( m_is_obj && !m_is_ref ) { // push objects to instantiate push_( reg_sp, (t_CKUINT)shred->obj_array ); // push index to use push_( reg_sp, 0 ); // push size push_( reg_sp, (t_CKUINT)num_obj ); } return; overflow: // we have a problem fprintf( stderr, "[chuck](VM): OverFlow: requested array size too big...\n" ); goto error; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while allocating arrays...\n" ); goto error; error: fprintf( stderr, "[chuck](VM): (note: in shred[id=%d:%s])\n", shred->xid, shred->name.c_str() ); // done shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Array_Access::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // UNUSED: t_CKUINT *& reg_sp = sp; t_CKINT i = 0; t_CKUINT val = 0; t_CKFLOAT fval = 0; // pop pop_( sp, 2 ); // check pointer if( !(*sp) ) goto null_pointer; // 4 or 8 if( m_size == 4 ) // ISSUE: 64-bit { // get array Chuck_Array4 * arr = (Chuck_Array4 *)(*sp); // get index i = (t_CKINT)(*(sp+1)); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( i ); // exception if( !val ) goto array_out_of_bound; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( i, &val ) ) goto array_out_of_bound; // push the value push_( sp, val ); } } else if( m_size == 8 ) // ISSUE: 64-bit { // get array Chuck_Array8 * arr = (Chuck_Array8 *)(*sp); // get index i = (t_CKINT)(*(sp+1)); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( i ); // exception if( !val ) goto array_out_of_bound; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( i, &fval ) ) goto array_out_of_bound; // push the value push_( ((t_CKFLOAT *&)sp), fval ); } } else assert( FALSE ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (array access) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; array_out_of_bound: // we have a problem fprintf( stderr, "[chuck](VM): ArrayOutofBounds: in shred[id=%d:%s], PC=[%d], index=[%d]\n", shred->xid, shred->name.c_str(), shred->pc, i ); // go to done goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Array_Map_Access::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * key = NULL; t_CKUINT val = 0; t_CKFLOAT fval = 0; // pop pop_( sp, 2 ); // check pointer if( !(*sp) ) goto null_pointer; // 4 or 8 if( m_size == 4 ) // ISSUE: 64-bit { // get array Chuck_Array4 * arr = (Chuck_Array4 *)(*sp); // get index key = (Chuck_String *)(*(sp+1)); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( key->str ); // exception if( !val ) goto error; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( key->str, &val ) ) goto error; // push the value push_( sp, val ); } } else if( m_size == 8 ) // ISSUE: 64-bit { // get array Chuck_Array8 * arr = (Chuck_Array8 *)(*sp); // get index key = (Chuck_String *)(*(sp+1)); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( key->str ); // exception if( !val ) goto error; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( key->str, &fval ) ) goto error; // push the value push_( ((t_CKFLOAT *&)sp), fval ); } } else assert( FALSE ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (map access) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; error: // we have a problem fprintf( stderr, "[chuck](VM): InternalArrayMap error: in shred[id=%d:%s], PC=[%d], index=[%s]\n", shred->xid, shred->name.c_str(), shred->pc, key->str.c_str() ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Array_Access_Multi::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // reg stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; t_CKINT i = 0; t_CKUINT val = 0, j; t_CKFLOAT fval = 0; t_CKINT * ptr = NULL; t_CKUINT index = 0; // pop all indices then array pop_( sp, m_depth + 1 ); // get array Chuck_Array4 * base = (Chuck_Array4 *)(*sp); ptr = (t_CKINT *)(sp+1); // check for null if( !base ) goto null_pointer; // make sure assert( m_depth > 1 ); // loop through indices for( j = 0; j < (m_depth-1); j++ ) { // get index i = *ptr++; // get the array if( !base->get( i, &val ) ) goto array_out_of_bound; // set the array base = (Chuck_Array4 *)val; // check for null if( !base ) { // error index = j + 1; goto null_pointer; } } // 4 or 8 if( m_size == 4 ) // ISSUE: 64-bit { // get arry Chuck_Array4 * arr = base; // get index i = (t_CKINT)(*ptr); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( i ); // exception if( !val ) goto array_out_of_bound; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( i, &val ) ) goto array_out_of_bound; // push the value push_( sp, val ); } } else if( m_size == 8 ) // ISSUE: 64-bit { // get array Chuck_Array8 * arr = (Chuck_Array8 *)(base); // get index i = (t_CKINT)(*ptr); // check if writing if( m_emit_addr ) { // get the addr val = arr->addr( i ); // exception if( !val ) goto array_out_of_bound; // push the addr push_( sp, val ); } else { // get the value if( !arr->get( i, &fval ) ) goto array_out_of_bound; // push the value push_( ((t_CKFLOAT *&)sp), fval ); } } else assert( FALSE ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (array access) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); fprintf( stderr, "[chuck](VM): (array dimension where exception occurred: %d)\n", index ); goto done; array_out_of_bound: // we have a problem fprintf( stderr, "[chuck](VM): ArrayOutofBounds: in shred[id=%d:%s], PC=[%d], index=[%d]\n", shred->xid, shred->name.c_str(), shred->pc, i ); // go to done goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dot_Member_Data::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // register stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // the pointer t_CKUINT data; // pop the object pointer pop_( sp, 1 ); // get the object pointer Chuck_Object * obj = (Chuck_Object *)(*sp); // check if( !obj ) goto error; // calculate the data pointer data = (t_CKUINT)(obj->data + m_offset); // emit addr or value if( m_emit_addr ) { // push the address push_( sp, data ); } else { // 4 or 8 if( m_size == 4 ) { push_( sp, *((t_CKUINT *)data) ); } // ISSUE: 64-bit else if( m_size == 8 ) { push_float( sp, *((t_CKFLOAT *)data) ); } // ISSUE: 64-bit else assert( FALSE ); } return; error: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: shred[id=%d:%s:(%d)], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dot_Member_Func::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // register stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // the pointer t_CKUINT data; // pop the object pointer pop_( sp, 1 ); // get the object pointer Chuck_Object * obj = (Chuck_Object *)(*sp); // check if( !obj ) goto error; // make sure we are in range assert( m_offset < obj->vtable->funcs.size() ); // calculate the data pointer data = (t_CKUINT)(obj->vtable->funcs[m_offset]); // push the address push_( sp, data ); return; error: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dot_Static_Data::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // register stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // the pointer t_CKUINT data; // pop the type pointer pop_( sp, 1 ); // get the object pointer Chuck_Type * t_class = (Chuck_Type *)(*sp); // make sure assert( (m_offset + m_size) <= t_class->info->class_data_size ); // calculate the data pointer data = (t_CKUINT)(t_class->info->class_data + m_offset); // emit addr or value if( m_emit_addr ) { // push the address push_( sp, data ); } else { // 4 or 8 if( m_size == 4 ) { push_( sp, *((t_CKUINT *)data) ); } // ISSUE: 64-bit else if( m_size == 8 ) { push_float( sp, *((t_CKFLOAT *)data) ); } // ISSUE: 64-bit else assert( FALSE ); } } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dot_Static_Import_Data::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // register stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // emit addr or value if( m_emit_addr ) { // push the address push_( sp, (t_CKUINT)m_addr ); } else { // 4 or 8 if( m_size == 4 ) { push_( sp, *((t_CKUINT *)m_addr) ); } // ISSUE: 64-bit else if( m_size == 8 ) { push_float( sp, *((t_CKFLOAT *)m_addr) ); } // ISSUE: 64-bit else assert( FALSE ); } } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Dot_Static_Func::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // register stack pointer t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; // pop the type pointer pop_( sp, 1 ); // push the address push_( sp, (t_CKUINT)(m_func) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Cast_double2int::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKFLOAT *& sp = (t_CKFLOAT *&)shred->reg->sp; t_CKINT *& sp_int = (t_CKINT *&)sp; pop_( sp, 1 ); push_( sp_int, (t_CKINT)(*sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Cast_int2double::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; t_CKFLOAT *& sp_double = (t_CKFLOAT *&)sp; pop_( sp, 1 ); push_( sp_double, (t_CKFLOAT)(*sp) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Op_string::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; Chuck_String * lhs = NULL; Chuck_String * rhs = NULL; // pop pop_( sp, 2 ); // get the string references lhs = (Chuck_String *)*sp; rhs = (Chuck_String *)*(sp + 1); // neither should be null if( !lhs || !rhs ) goto null_pointer; // look switch( m_val ) { case ae_op_eq: push_( sp, lhs->str == rhs->str ); break; case ae_op_neq: push_( sp, lhs->str != rhs->str ); break; case ae_op_lt: push_( sp, lhs->str < rhs->str ); break; case ae_op_le: push_( sp, lhs->str <= rhs->str ); break; case ae_op_gt: push_( sp, lhs->str > rhs->str ); break; case ae_op_ge: push_( sp, lhs->str >= rhs->str ); break; default: goto invalid_op; break; } return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (during string op) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); goto done; invalid_op: // we have a problem fprintf( stderr, "[chuck](VM): InvalidStringOpException: '%d' in shred[id=%d:%s], PC=[%d]\n", m_val, shred->xid, shred->name.c_str(), shred->pc ); goto done; done: // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_ADC::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; push_( reg_sp, (t_CKUINT)vm->m_adc ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_DAC::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; push_( reg_sp, (t_CKUINT)vm->m_dac ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Bunghole::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& reg_sp = (t_CKUINT *&)shred->reg->sp; push_( reg_sp, (t_CKUINT)vm->m_bunghole ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_Link::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { Chuck_UGen **& sp = (Chuck_UGen **&)shred->reg->sp; // pop pop_( sp, 2 ); // check for null if( !*(sp+1) || !(*sp) ) goto null_pointer; // go for it (*(sp + 1))->add( *sp ); // push the second push_( sp, *(sp + 1) ); return; null_pointer: // we have a problem fprintf( stderr, "[chuck](VM): NullPointerException: (UGen link) in shred[id=%d:%s], PC=[%d]\n", shred->xid, shred->name.c_str(), shred->pc ); // do something! shred->is_running = FALSE; shred->is_done = TRUE; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_UnLink::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { Chuck_UGen **& sp = (Chuck_UGen **&)shred->reg->sp; pop_( sp, 2 ); (*(sp+1))->remove( *sp ); push_( sp, *(sp + 1) ); } /* //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_Ctrl::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 4 ); Chuck_UGen * ugen = (Chuck_UGen *)*(sp+1); f_ctrl ctrl = (f_ctrl)*(sp+2); f_cget cget = (f_cget)*(sp+3); // set now ugen->now = shred->now; // call ctrl ctrl( ugen, (void *)sp ); if( cget ) cget( ugen, (void *)sp ); // push the new value push_( sp, *sp); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_CGet::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); Chuck_UGen * ugen = (Chuck_UGen *)*(sp); f_cget cget = (f_cget)*(sp+1); // set now ugen->now = shred->now; // call cget cget( ugen, (void *)sp ); // push the new value push_( sp, *sp); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_Ctrl2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 4 ); Chuck_UGen * ugen = (Chuck_UGen *)*(sp+1); f_ctrl ctrl = (f_ctrl)*(sp+2); f_cget cget = (f_cget)*(sp+3); // set now ugen->now = shred->now; // call ctrl pop_( sp, 1 ); ctrl( ugen, (void *)sp ); if( cget ) cget( ugen, (void *)sp ); // push the new value ((t_CKFLOAT *&)shred->reg->sp)++; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_CGet2::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKUINT *& sp = (t_CKUINT *&)shred->reg->sp; pop_( sp, 2 ); Chuck_UGen * ugen = (Chuck_UGen *)*(sp); f_cget cget = (f_cget)*(sp+1); // set now ugen->now = shred->now; // call cget cget( ugen, (void *)sp ); // push the new value ((t_CKFLOAT *&)shred->reg->sp)++; } */ //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_UGen_PMsg::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { Chuck_UGen **& sp = (Chuck_UGen **&)shred->reg->sp; pop_( sp, 2 ); // (*(sp + 1))->pmsg( shred->now, *sp ); push_( sp, *(sp + 1) ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- void Chuck_Instr_Init_Loop_Counter::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKINT *& sp = (t_CKINT *&)shred->reg->sp; // pop the value pop_( sp, 1 ); // copy it (*(t_CKINT *)m_val) = *sp >= 0 ? *sp : -*sp; } // hack Chuck_Instr_Hack::Chuck_Instr_Hack( Chuck_Type * type ) { this->m_type_ref = type; // this->m_type_ref->add_ref(); } Chuck_Instr_Hack::~Chuck_Instr_Hack() { // this->m_type_ref->release(); } void Chuck_Instr_Hack::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { // look at the type if( m_type_ref->size == 4 ) // ISSUE: 64-bit { t_CKINT * sp = (t_CKINT *)shred->reg->sp; if( !isa( m_type_ref, &t_string ) ) // print it fprintf( stderr, "%d :(%s)\n", *(sp-1), m_type_ref->c_name() ); else fprintf( stderr, "\"%s\" : (%s)\n", ((Chuck_String *)*(sp-1))->str.c_str(), m_type_ref->c_name() ); } else if( m_type_ref->size == 8 ) // ISSUE: 64-bit { t_CKFLOAT * sp = (t_CKFLOAT *)shred->reg->sp; // print it fprintf( stderr, "%f :(%s)\n", *(sp-1), m_type_ref->c_name() ); } else if( m_type_ref->size == 0 ) { fprintf( stderr, "... :(%s)\n", m_type_ref->c_name() ); } else assert( FALSE ); // flush fflush( stderr ); } const char * Chuck_Instr_Hack::params() const { static char buffer[256]; sprintf( buffer, "(%s)", m_type_ref->c_name() ); return buffer; } // gack Chuck_Instr_Gack::Chuck_Instr_Gack( const std::vector & types ) { m_type_refs = types; // add refs } Chuck_Instr_Gack::~Chuck_Instr_Gack() { // release refs } void Chuck_Instr_Gack::execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) { t_CKBYTE * the_sp = (t_CKBYTE *)shred->reg->sp; if( m_type_refs.size() == 1 ) { Chuck_Instr_Hack hack( m_type_refs[0] ); hack.execute( vm, shred ); return; } // loop over types t_CKUINT i; // find the start of the expression for( i = 0; i < m_type_refs.size(); i++ ) { Chuck_Type * type = m_type_refs[i]; the_sp -= type->size; } // print for( i = 0; i < m_type_refs.size(); i++ ) { Chuck_Type * type = m_type_refs[i]; // look at the type if( type->size == 4 ) // ISSUE: 64-bit { t_CKINT * sp = (t_CKINT *)the_sp; if( !isa( type, &t_string ) ) { if( isa( type, &t_object ) ) // print it fprintf( stderr, "0x%x ", *(sp) ); else // print it fprintf( stderr, "%d ", *(sp) ); } else fprintf( stderr, "%s ", ((Chuck_String *)*(sp))->str.c_str() ); the_sp += 4; } else if( type->size == 8 ) // ISSUE: 64-bit { t_CKFLOAT * sp = (t_CKFLOAT *)the_sp; // print it fprintf( stderr, "%f ", *(sp) ); the_sp += 8; } else if( type->size == 0 ) { fprintf( stderr, "... " ); } else assert( FALSE ); } fprintf( stderr, "\n" ); // flush fflush( stderr ); } const char * Chuck_Instr_Gack::params() const { static char buffer[256]; sprintf( buffer, "( many types )" ); return buffer; } chuck-1.2.0.8.dfsg/src/chuck_instr.h0000644000175000017500000021556210600421722015626 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_instr.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_INSTR_H__ #define __CHUCK_INSTR_H__ #include #include "chuck_def.h" #include // forward reference struct Chuck_VM; struct Chuck_VM_Shred; struct Chuck_Type; struct Chuck_Func; //----------------------------------------------------------------------------- // name: struct Chuck_Instr // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr { public: virtual ~Chuck_Instr() { } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ) = 0; public: virtual const char * name() const; virtual const char * params() const { return ""; } }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Op // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Op : public Chuck_Instr { public: inline void set( t_CKUINT jmp ) { m_jmp = jmp; } public: virtual const char * params() const { static char buffer[256]; sprintf( buffer, "%ld", m_jmp ); return buffer; } protected: t_CKUINT m_jmp; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Unary_Op // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Unary_Op : public Chuck_Instr { public: inline void set( t_CKUINT val ) { m_val = val; } inline t_CKUINT get() { return m_val; } public: virtual const char * params() const { static char buffer[256]; sprintf( buffer, "%ld", m_val ); return buffer; } protected: t_CKUINT m_val; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Unary_Op2 // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Unary_Op2 : public Chuck_Instr { public: inline void set( t_CKFLOAT val ) { m_val = val; } inline t_CKFLOAT get() { return m_val; } public: virtual const char * params() const { static char buffer[256]; sprintf( buffer, "%.6f", m_val ); return buffer; } protected: t_CKFLOAT m_val; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Op // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Op : public Chuck_Instr { }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_PreInc_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_PreInc_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_PostInc_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_PostInc_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_PreDec_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_PreDec_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_PostDec_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_PostDec_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dec_int_Addr // desc: decrement int value at addr //----------------------------------------------------------------------------- struct Chuck_Instr_Dec_int_Addr : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Dec_int_Addr( t_CKUINT src ) { this->set( src ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Complement_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Complement_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_int_Reverse // desc: same as mod_int, operands reversed, for %=> //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_int_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_int_Reverse // desc: same as minus_int, operands reversed, for -=> //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_int_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Times_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Times_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_int_Reverse // desc: same as divide_int, operands reversed, for /=> //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_int_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_double_Reverse // desc: same as minus_double, operands reversed, for -=> //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_double_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Times_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Times_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_double_Reverse // desc: same as divide_double, operands reversed, for /=> //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_double_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_double_Reverse // desc: same as mod_double, operands reversed, for %=> //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_double_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_int_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_int_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_int_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_int_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_int_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_int_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Times_int_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Times_int_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_int_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_int_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_double_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_double_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Minus_double_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Minus_double_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Times_double_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Times_double_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Divide_double_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Divide_double_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mod_double_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Mod_double_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_string // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_string : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_string_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_string_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_string_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_string_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_string_float // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_string_float : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_int_string // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_int_string : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_float_string // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_float_string : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_int_string_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_int_string_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Add_float_string_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Add_float_string_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Lt_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Lt_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Lt_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Gt_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Gt_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Gt_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Le_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Le_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Le_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Ge_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Ge_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Ge_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Eq_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Eq_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Eq_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Neq_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Neq_int : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Neq_int( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Lt_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Lt_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Lt_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Gt_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Gt_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Gt_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Le_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Le_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Le_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Ge_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Ge_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Ge_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Eq_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Eq_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Eq_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Branch_Neq_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Branch_Neq_double : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Branch_Neq_double( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Lt_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Lt_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Gt_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Gt_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Le_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Le_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Ge_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Ge_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Eq_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Eq_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Neq_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Neq_int : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Not_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Not_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Negate_int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Negate_int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Negate_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Negate_double : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Lt_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Lt_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Gt_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Gt_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Le_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Le_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Ge_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Ge_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Eq_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Eq_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Neq_double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Neq_double : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_And // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_And : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Or // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Or : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Xor // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Xor : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Right // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Right : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Right_Reverse // desc: same as shift_right, operands reversed, for >>=> //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Right_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Left // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Left : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Left_Reverse // desc: same as shift_left, operands reversed, for <<=> //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Left_Reverse : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_And_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_And_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Or_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Or_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Xor_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Xor_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Right_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Right_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Binary_Shift_Left_Assign // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Binary_Shift_Left_Assign : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_And // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_And : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Or // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Or : public Chuck_Instr_Binary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Goto // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Goto : public Chuck_Instr_Branch_Op { public: Chuck_Instr_Goto( t_CKUINT jmp ) { this->set( jmp ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Pop_Word // desc: pop word from reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Pop_Word : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Pop_Word2 // desc: pop t_CKFLOAT word from reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Pop_Word2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Pop_Word3 // desc: pop arbitrary num of word from reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Pop_Word3 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Pop_Word3( t_CKUINT num ) { this->set( num ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Pop_Mem // desc: pop word, and copy it to the mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Pop_Mem: public Chuck_Instr_Unary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Pop_Mem2 // desc: pop t_CKFLOAT word, and copy it to the mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Pop_Mem2: public Chuck_Instr_Unary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Imm // desc: push immediate to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Imm : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Push_Imm( t_CKUINT val ) { this->set( val ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Imm2 // desc: push t_CKFLOAT immediate to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Imm2 : public Chuck_Instr_Unary_Op2 { public: Chuck_Instr_Reg_Push_Imm2( t_CKFLOAT val ) { this->set( val ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Dup_Last // desc: duplicate last value on reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Dup_Last : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Dup_Last2 // desc: duplicate last float on reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Dup_Last2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Now // desc: push value of now to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Now : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Me // desc: push value of me to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Me : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_This // desc: push value of now to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_This : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Start // desc: push value of start to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Start : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Maybe // desc: push immediate to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Maybe : public Chuck_Instr_Unary_Op { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Mem // desc: push a variable from mem stack to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Mem : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Push_Mem( t_CKUINT src, t_CKBOOL use_base = FALSE ) { this->set( src ); base = use_base; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "src=%ld, base=%ld", m_val, base ); return buffer; } protected: // use global stack base t_CKBOOL base; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Mem2 // desc: push a t_CKFLOAT variable from mem stack to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Mem2 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Push_Mem2( t_CKUINT src, t_CKBOOL use_base = FALSE ) { this->set( src ); base = use_base; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "src=%ld, base=%ld", m_val, base ); return buffer; } protected: // use global stack base t_CKBOOL base; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Mem_Addr // desc: push addr from mem stack to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Mem_Addr : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Push_Mem_Addr( t_CKUINT src, t_CKBOOL use_base ) { this->set( src ); base = use_base; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "src=%ld, base=%ld", m_val, base ); return buffer; } protected: // use global stack base t_CKBOOL base; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Deref // desc: push value from pointer //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Deref : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Reg_Push_Deref( t_CKUINT src, t_CKUINT size ) { this->set( src ); m_size = size; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); t_CKUINT m_size; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Reg_Push_Deref // desc: push a t_CKFLOAT variable from main memory to reg stack //----------------------------------------------------------------------------- struct Chuck_Instr_Reg_Push_Deref2 : public Chuck_Instr_Unary_Op2 { public: Chuck_Instr_Reg_Push_Deref2( t_CKFLOAT src ) { this->set( src ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Set_Imm // desc: set a value unto mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Set_Imm : public Chuck_Instr { public: Chuck_Instr_Mem_Set_Imm( t_CKUINT offset, t_CKUINT val ) { m_offset = offset; m_val = val; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "offset=%ld, value=%ld", m_offset, m_val ); return buffer; } protected: t_CKUINT m_offset; t_CKUINT m_val; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Set_Imm2 // desc: set a value unto mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Set_Imm2 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Mem_Set_Imm2( t_CKUINT offset, t_CKFLOAT val ) { m_offset = offset; m_val = val; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "offset=%ld, value=%f", m_offset, m_val ); return buffer; } protected: t_CKUINT m_offset; t_CKFLOAT m_val; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Push_Imm // desc: push a value unto mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Push_Imm : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Mem_Push_Imm( t_CKUINT src ) { this->set( src ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Push_Imm2 // desc: push a t_CKFLOAT value unto mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Push_Imm2 : public Chuck_Instr_Unary_Op2 { public: Chuck_Instr_Mem_Push_Imm2( t_CKFLOAT src ) { this->set( src ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Pop_Word // desc: pop a value from mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Pop_Word : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Pop_Word2 // desc: pop a value from mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Pop_Word2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Mem_Pop_Word2 // desc: pop a value from mem stack //----------------------------------------------------------------------------- struct Chuck_Instr_Mem_Pop_Word3 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Mem_Pop_Word3( t_CKUINT num ) { this->set( num ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Nop // desc: no op //----------------------------------------------------------------------------- struct Chuck_Instr_Nop : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_EOC // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_EOC : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Alloc_Word // desc: alloc local - leaves addr on operand stack //----------------------------------------------------------------------------- struct Chuck_Instr_Alloc_Word : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Alloc_Word( t_CKUINT offset ) { this->set( offset ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Alloc_Word2 // desc: alloc local - leaves addr on operand stack //----------------------------------------------------------------------------- struct Chuck_Instr_Alloc_Word2 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Alloc_Word2( t_CKUINT offset ) { this->set( offset ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Alloc_Member_Word // desc: alloc member - leaves addr on operand stack //----------------------------------------------------------------------------- struct Chuck_Instr_Alloc_Member_Word : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Alloc_Member_Word( t_CKUINT offset ) { this->set( offset ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Alloc_Member_Word2 // desc: alloc member - leaves addr on operand stack //----------------------------------------------------------------------------- struct Chuck_Instr_Alloc_Member_Word2 : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Alloc_Member_Word2( t_CKUINT offset ) { this->set( offset ); } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Instantiate_Object // desc: instantiate object - leaves reference value on operand stack //----------------------------------------------------------------------------- struct Chuck_Instr_Instantiate_Object : public Chuck_Instr { public: Chuck_Instr_Instantiate_Object( Chuck_Type * t ) { this->type = t; } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const; public: Chuck_Type * type; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Pre_Constructor // desc: preconstruct object //----------------------------------------------------------------------------- struct Chuck_Instr_Pre_Constructor : public Chuck_Instr { public: Chuck_Instr_Pre_Constructor( Chuck_VM_Code * pre, t_CKUINT offset ) { pre_ctor = pre; this->stack_offset = offset; } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); // virtual const char * params() const; public: Chuck_VM_Code * pre_ctor; t_CKUINT stack_offset; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Pre_Ctor_Array_Top // desc: preconstruct object in array (top) //----------------------------------------------------------------------------- struct Chuck_Instr_Pre_Ctor_Array_Top : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Pre_Ctor_Array_Top( Chuck_Type * t ) { this->type = t; } virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); // virtual const char * params() const; public: Chuck_Type * type; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Pre_Ctor_Array_Bottom // desc: preconstruct object in array (bottom) //----------------------------------------------------------------------------- struct Chuck_Instr_Pre_Ctor_Array_Bottom : public Chuck_Instr_Unary_Op { virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); // virtual const char * params() const; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Pre_Ctor_Array_Post // desc: preconstruct object in array (clean up) //----------------------------------------------------------------------------- struct Chuck_Instr_Pre_Ctor_Array_Post : public Chuck_Instr { virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); // virtual const char * params() const; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Assign_String // desc: assign primitive (string) //----------------------------------------------------------------------------- struct Chuck_Instr_Assign_String : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Assign_Primitive // desc: assign primitive (word) //----------------------------------------------------------------------------- struct Chuck_Instr_Assign_Primitive : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Assign_Primitive2 // desc: assign primitive (2 word) //----------------------------------------------------------------------------- struct Chuck_Instr_Assign_Primitive2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Assign_Object // desc: assign object with reference counting and releasing previous reference //----------------------------------------------------------------------------- struct Chuck_Instr_Assign_Object : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Assign_Object // desc: map object with reference counting and releasing previous reference //----------------------------------------------------------------------------- struct Chuck_Instr_Assign_Object_To_Map : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Assign_Object_To_Map( t_CKUINT size ) { this->set( size ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Chuck_Release_Object // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Chuck_Release_Object : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Func_To_Code // desc: Chuck_Func * to Chuck_VM_Code * //----------------------------------------------------------------------------- struct Chuck_Instr_Func_To_Code : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Func_Call // desc: user-defined function call //----------------------------------------------------------------------------- struct Chuck_Instr_Func_Call : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Func_Call_Member // desc: imported member function call with return //----------------------------------------------------------------------------- struct Chuck_Instr_Func_Call_Member : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Func_Call_Member( t_CKUINT ret_size ) { this->set( ret_size ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Func_Call_Static // desc: imported static function call with return //----------------------------------------------------------------------------- struct Chuck_Instr_Func_Call_Static : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Func_Call_Static( t_CKUINT ret_size ) { this->set( ret_size ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Func_Return // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Func_Return : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Spork // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Spork : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Spork( t_CKUINT v = 0 ) { this->set( v ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Time_Advance // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Time_Advance : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Event_Wait // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Event_Wait : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Array_Init // desc: for [ ... ] values //----------------------------------------------------------------------------- struct Chuck_Instr_Array_Init : public Chuck_Instr { public: Chuck_Instr_Array_Init( Chuck_Type * the_type, t_CKINT length ); virtual ~Chuck_Instr_Array_Init(); public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { return m_param_str; } protected: Chuck_Type * m_type_ref; t_CKINT m_length; t_CKBOOL m_is_obj; char * m_param_str; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Array_Alloc // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Array_Alloc : public Chuck_Instr { public: Chuck_Instr_Array_Alloc( t_CKUINT depth, Chuck_Type * the_type, t_CKUINT offset, t_CKBOOL ref ); virtual ~Chuck_Instr_Array_Alloc(); public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { return m_param_str; } protected: t_CKUINT m_depth; Chuck_Type * m_type_ref; t_CKBOOL m_is_obj; char * m_param_str; t_CKUINT m_stack_offset; t_CKBOOL m_is_ref; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Array_Access // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Array_Access : public Chuck_Instr { public: Chuck_Instr_Array_Access( t_CKUINT size, t_CKUINT emit_addr, t_CKUINT istr = FALSE ) { m_size = size; m_emit_addr = emit_addr; m_istr = istr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "size=%ld, emit_addr=%ld istr=%ld", m_size, m_emit_addr, m_istr ); return buffer; } protected: t_CKUINT m_size; t_CKUINT m_emit_addr; t_CKUINT m_istr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Array_Map_Access // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Array_Map_Access : public Chuck_Instr { public: Chuck_Instr_Array_Map_Access( t_CKUINT size, t_CKUINT emit_addr ) { m_size = size; m_emit_addr = emit_addr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "size=%ld, emit_addr=%ld", m_size, m_emit_addr ); return buffer; } protected: t_CKUINT m_size; t_CKUINT m_emit_addr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Array_Access_Multi // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Array_Access_Multi : public Chuck_Instr { public: Chuck_Instr_Array_Access_Multi( t_CKUINT depth, t_CKUINT size, t_CKUINT emit_addr ) { m_size = size; m_depth = depth; m_emit_addr = emit_addr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "depth=%ld, size=%ld, emit_addr=%ld", m_depth, m_size, m_emit_addr ); return buffer; } protected: t_CKUINT m_depth; t_CKUINT m_size; t_CKUINT m_emit_addr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dot_Member_Data // desc: access the member data of object by offset //----------------------------------------------------------------------------- struct Chuck_Instr_Dot_Member_Data : public Chuck_Instr { public: Chuck_Instr_Dot_Member_Data( t_CKUINT offset, t_CKUINT size, t_CKUINT emit_addr ) { m_offset = offset; m_size = size; m_emit_addr = emit_addr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "offset=%ld, size=%ld, emit_addr=%ld", m_offset, m_size, m_emit_addr ); return buffer; } protected: t_CKUINT m_offset; t_CKUINT m_size; t_CKUINT m_emit_addr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dot_Member_Func // desc: access the member function of object by offset //----------------------------------------------------------------------------- struct Chuck_Instr_Dot_Member_Func : public Chuck_Instr { public: Chuck_Instr_Dot_Member_Func( t_CKUINT offset ) { m_offset = offset; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "offset=%ld", m_offset ); return buffer; } protected: t_CKUINT m_offset; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dot_Static_Data // desc: access the static data of object by offset //----------------------------------------------------------------------------- struct Chuck_Instr_Dot_Static_Data : public Chuck_Instr { public: Chuck_Instr_Dot_Static_Data( t_CKUINT offset, t_CKUINT size, t_CKUINT emit_addr ) { m_offset = offset; m_size = size; m_emit_addr = emit_addr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "offset=%ld, size=%ld, emit_addr=%ld", m_offset, m_size, m_emit_addr ); return buffer; } protected: t_CKUINT m_offset; t_CKUINT m_size; t_CKUINT m_emit_addr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dot_Static_Import_Data // desc: access the static data of object by pointer //----------------------------------------------------------------------------- struct Chuck_Instr_Dot_Static_Import_Data : public Chuck_Instr { public: Chuck_Instr_Dot_Static_Import_Data( void * addr, t_CKUINT size, t_CKUINT emit_addr ) { m_addr = addr; m_size = size; m_emit_addr = emit_addr; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "addr=%ld, size=%ld, emit_addr=%ld", (t_CKUINT)m_addr, m_size, m_emit_addr ); return buffer; } protected: void * m_addr; t_CKUINT m_size; t_CKUINT m_emit_addr; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Dot_Static_Func // desc: access the static function of object //----------------------------------------------------------------------------- struct Chuck_Instr_Dot_Static_Func : public Chuck_Instr { public: Chuck_Instr_Dot_Static_Func( Chuck_Func * func ) { m_func = func; } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const { static char buffer[256]; sprintf( buffer, "func=%ld", (t_CKUINT)m_func ); return buffer; } protected: Chuck_Func * m_func; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_ADC // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_ADC : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_DAC // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_DAC : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Bunghole // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Bunghole : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_Link // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_Link : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_UnLink // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_UnLink : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_Ctrl // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_Ctrl : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_CGet // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_CGet : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_Ctrl2 // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_Ctrl2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_CGet2 // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_CGet2 : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_UGen_PMsg // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_UGen_PMsg : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Cast_double2int // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Cast_double2int : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Cast_int2double // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Cast_int2double : public Chuck_Instr { public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Op_string // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Op_string : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Op_string( t_CKUINT v ) { this->set( v ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Init_Loop_Counter // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Init_Loop_Counter : public Chuck_Instr_Unary_Op { public: Chuck_Instr_Init_Loop_Counter( t_CKUINT v ) { this->set( v ); } public: virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Hack // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Hack : public Chuck_Instr { public: Chuck_Instr_Hack( Chuck_Type * type ); virtual ~Chuck_Instr_Hack(); virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const; protected: Chuck_Type * m_type_ref; }; //----------------------------------------------------------------------------- // name: struct Chuck_Instr_Gack // desc: ... //----------------------------------------------------------------------------- struct Chuck_Instr_Gack : public Chuck_Instr { public: Chuck_Instr_Gack( const std::vector & types ); virtual ~Chuck_Instr_Gack(); virtual void execute( Chuck_VM * vm, Chuck_VM_Shred * shred ); virtual const char * params() const; protected: std::vector m_type_refs; }; // runtime functions Chuck_Object * instantiate_and_initialize_object( Chuck_Type * type, Chuck_VM_Shred * shred ); // initialize object using Type t_CKBOOL initialize_object( Chuck_Object * obj, Chuck_Type * type ); // define SP offset #define push_( sp, val ) *(sp) = (val); (sp)++ #define push_float( sp, val ) *((t_CKFLOAT *&)sp) = (val); ((t_CKFLOAT *&)sp)++ #define pop_( sp, n ) sp -= (n) #define val_( sp ) *(sp) // stack overflow detection #define overflow_( stack ) ( stack->sp > stack->sp_max ) #define underflow_( stack ) ( stack->sp < stack->stack ) #endif chuck-1.2.0.8.dfsg/src/chuck_lang.cpp0000644000175000017500000022325410600421722015740 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_lang.cpp // desc: chuck class library base // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2005 //----------------------------------------------------------------------------- #include "chuck_lang.h" #include "chuck_type.h" #include "chuck_instr.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "midiio_rtmidi.h" #include "hidio_sdl.h" #include "util_string.h" // offset for member variable static t_CKUINT object_offset_m_testID = CK_INVALID_OFFSET; // storage for static variable static t_CKINT object_our_testID = 0; // dac tick // UGEN_TICK __ugen_tick( Chuck_Object * SELF, SAMPLE in, SAMPLE * out, Chuck_VM_Shred * SHRED ) CK_DLL_TICK(__ugen_tick) { *out = in; return TRUE; } //----------------------------------------------------------------------------- // name: init_class_object() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type ) { Chuck_DL_Func * func = NULL; // log EM_log( CK_LOG_SEVERE, "class 'object'" ); // init as base class if( !type_engine_import_class_begin( env, type, env->global(), object_ctor, object_dtor ) ) return FALSE; // add setTestID() func = make_new_mfun( "int", "testID", object_setTestID ); func->add_arg( "int", "id" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add getTestID() func = make_new_mfun( "int", "testID", object_getTestID ); if( !type_engine_import_mfun( env, func ) ) goto error; // add getTest() func = make_new_sfun( "int", "testStatic", object_testStatic ); func->add_arg( "float", "i" ); if( !type_engine_import_sfun( env, func ) ) goto error; // add member variable object_offset_m_testID = type_engine_import_mvar( env, "int", "m_testID", FALSE ); if( object_offset_m_testID == CK_INVALID_OFFSET ) goto error; // add static variable if( !type_engine_import_svar( env, "int", "our_testID", FALSE, (t_CKUINT)&object_our_testID ) ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: init_class_ugen() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type ) { Chuck_DL_Func * func = NULL; EM_log( CK_LOG_SEVERE, "class 'ugen'" ); //the type argument IS t_ugen here - there's no other use of this function //why are we using t_ugen here instead of type ( or vice versa ) ? PLD // add ugen info t_ugen.ugen_info = new Chuck_UGen_Info; t_ugen.ugen_info->add_ref(); t_ugen.ugen_info->tick = __ugen_tick; t_ugen.ugen_info->num_ins = 1; t_ugen.ugen_info->num_outs = 1; // init as base class // TODO: ctor/dtor, ugen's sometimes created internally? if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) return FALSE; // add setTestID() //func = make_new_mfun( "int", "testID", ugen_setTestID ); //func->add_arg( "int", "id" ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add getTestID() // func = make_new_mfun( "int", "testID", ugen_getTestID ); // if( !type_engine_import_mfun( env, func ) ) goto error; // gain func = make_new_mfun( "float", "gain", ugen_gain ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "gain", ugen_cget_gain ); if( !type_engine_import_mfun( env, func ) ) goto error; /* // next func = make_new_mfun( "float", "next", ugen_next ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "next", ugen_cget_next ); if( !type_engine_import_mfun( env, func ) ) goto error; */ // last func = make_new_mfun( "float", "last", ugen_last ); if( !type_engine_import_mfun( env, func ) ) goto error; // op func = make_new_mfun( "int", "op", ugen_op ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "op", ugen_cget_op ); if( !type_engine_import_mfun( env, func ) ) goto error; // add numChannels func = make_new_mfun( "int", "channels", ugen_numChannels ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "channels", ugen_cget_numChannels ); if( !type_engine_import_mfun( env, func ) ) goto error; // add chan func = make_new_mfun( "UGen", "chan", ugen_chan ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add isConnectedTo func = make_new_mfun( "int", "isConnectedTo", ugen_connected ); func->add_arg( "UGen", "right" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } // static t_CKUINT event_offset_data = 0; //----------------------------------------------------------------------------- // name: init_class_event() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type ) { Chuck_DL_Func * func = NULL; Chuck_Value * value = NULL; // log EM_log( CK_LOG_SEVERE, "class 'event'" ); // init as base class // TODO: ctor/dtor? if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) return FALSE; // add signal() func = make_new_mfun( "void", "signal", event_signal ); if( !type_engine_import_mfun( env, func ) ) goto error; // add broadcast() func = make_new_mfun( "void", "broadcast", event_broadcast ); if( !type_engine_import_mfun( env, func ) ) goto error; // add wait() func = make_new_mfun( "void", "wait", event_wait ); func->add_arg( "Shred", "me" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add can_wait() func = make_new_mfun( "int", "can_wait", event_can_wait ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); // find the offset for can_wait value = type_engine_find_value( type, "can_wait" ); assert( value != NULL ); assert( value->func_ref != NULL ); // remember it Chuck_Event::our_can_wait = value->func_ref->vt_index; return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } static t_CKUINT shred_offset_args = 0; //----------------------------------------------------------------------------- // name: init_class_shred() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type ) { // init as base class Chuck_DL_Func * func = NULL; // log EM_log( CK_LOG_SEVERE, "class 'shred'" ); // init as base class // TODO: ctor/dtor? if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) return FALSE; // add dtor // not // add clone() func = make_new_mfun( "void", "clone", shred_clone ); if( !type_engine_import_mfun( env, func ) ) goto error; // add exit() func = make_new_mfun( "void", "exit", shred_exit ); if( !type_engine_import_mfun( env, func ) ) goto error; // add id() func = make_new_mfun( "int", "id", shred_id ); if( !type_engine_import_mfun( env, func ) ) goto error; // add yield() func = make_new_mfun( "void", "yield", shred_yield ); if( !type_engine_import_mfun( env, func ) ) goto error; // add nargs() // func = make_new_mfun( "int", "numArgs", shred_numArgs ); // if( !type_engine_import_mfun( env, func ) ) goto error; // add nargs() func = make_new_mfun( "int", "args", shred_numArgs ); if( !type_engine_import_mfun( env, func ) ) goto error; // add arg() // func = make_new_mfun( "string", "getArg", shred_getArg ); // func->add_arg( "int", "index" ); // if( !type_engine_import_mfun( env, func ) ) goto error; // add arg() func = make_new_mfun( "string", "arg", shred_getArg ); func->add_arg( "int", "index" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: init_class_string() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type ) { // init as base class Chuck_DL_Func * func = NULL; // log EM_log( CK_LOG_SEVERE, "class 'string'" ); // init as base class // TODO: ctor/dtor if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) return FALSE; // add length() func = make_new_mfun( "int", "length", string_length ); if( !type_engine_import_mfun( env, func ) ) goto error; // add upper() func = make_new_mfun( "string", "upper", string_upper ); if( !type_engine_import_mfun( env, func ) ) goto error; // add lower() func = make_new_mfun( "string", "lower", string_lower ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ltrim() func = make_new_mfun( "string", "ltrim", string_ltrim ); if( !type_engine_import_mfun( env, func ) ) goto error; // add rtrim() func = make_new_mfun( "string", "rtrim", string_rtrim ); if( !type_engine_import_mfun( env, func ) ) goto error; // add trim() func = make_new_mfun( "string", "trim", string_trim ); if( !type_engine_import_mfun( env, func ) ) goto error; /* // add at() func = make_new_mfun( "int", "ch", string_set_at ); func->add_arg( "int", "index" ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "ch", string_get_at ); func->add_arg( "int", "index" ); if( !type_engine_import_mfun( env, func ) ) goto error; */ // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: init_class_array() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type ) { // init as base class Chuck_DL_Func * func = NULL; // log EM_log( CK_LOG_SEVERE, "class 'array'" ); // init as base class // TODO: ctor/dtor? if( !type_engine_import_class_begin( env, type, env->global(), NULL, NULL ) ) return FALSE; // add clear() func = make_new_mfun( "void", "clear", array_clear ); if( !type_engine_import_mfun( env, func ) ) goto error; // add size() func = make_new_mfun( "int", "size", array_size ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cap() func = make_new_mfun( "int", "cap", array_set_capacity ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "cap", array_get_capacity ); if( !type_engine_import_mfun( env, func ) ) goto error; // add find() func = make_new_mfun( "int", "find", array_find ); func->add_arg( "string", "key" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add erase() func = make_new_mfun( "int", "erase", array_erase ); func->add_arg( "string", "key" ); if( !type_engine_import_mfun( env, func ) ) goto error; type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } // static static t_CKUINT MidiIn_offset_data = 0; static t_CKUINT MidiMsg_offset_data1 = 0; static t_CKUINT MidiMsg_offset_data2 = 0; static t_CKUINT MidiMsg_offset_data3 = 0; static t_CKUINT MidiMsg_offset_when = 0; static t_CKUINT MidiOut_offset_data = 0; //----------------------------------------------------------------------------- // name: init_class_Midi() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_Midi( Chuck_Env * env ) { Chuck_DL_Func * func = NULL; // init base class // TODO: ctor/dtor? if( !type_engine_import_class_begin( env, "MidiMsg", "Object", env->global(), NULL, NULL ) ) return FALSE; // add member variable MidiMsg_offset_data1 = type_engine_import_mvar( env, "int", "data1", FALSE ); if( MidiMsg_offset_data1 == CK_INVALID_OFFSET ) goto error; // add member variable MidiMsg_offset_data2 = type_engine_import_mvar( env, "int", "data2", FALSE ); if( MidiMsg_offset_data2 == CK_INVALID_OFFSET ) goto error; // add member variable MidiMsg_offset_data3 = type_engine_import_mvar( env, "int", "data3", FALSE ); if( MidiMsg_offset_data3 == CK_INVALID_OFFSET ) goto error; // add member variable MidiMsg_offset_when = type_engine_import_mvar( env, "time", "when", FALSE ); if( MidiMsg_offset_when == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "MidiIn", "Event", env->global(), MidiIn_ctor, MidiIn_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiIn_open ); func->add_arg( "int", "port" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add good() func = make_new_mfun( "int", "good", MidiIn_good ); if( !type_engine_import_mfun( env, func ) ) goto error; // add num() func = make_new_mfun( "int", "num", MidiIn_num ); if( !type_engine_import_mfun( env, func ) ) goto error; // add name() func = make_new_mfun( "string", "name", MidiIn_name ); if( !type_engine_import_mfun( env, func ) ) goto error; // add printerr() func = make_new_mfun( "void", "printerr", MidiIn_printerr ); func->add_arg( "int", "print_or_not" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add recv() func = make_new_mfun( "int", "recv", MidiIn_recv ); func->add_arg( "MidiMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add can_wait() func = make_new_mfun( "int", "can_wait", MidiIn_can_wait ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable MidiIn_offset_data = type_engine_import_mvar( env, "int", "@MidiIn_data", FALSE ); if( MidiIn_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "MidiOut", "Object", env->global(), MidiOut_ctor, MidiOut_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiOut_open ); func->add_arg( "int", "port" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add good() func = make_new_mfun( "int", "good", MidiOut_good ); if( !type_engine_import_mfun( env, func ) ) goto error; // add num() func = make_new_mfun( "int", "num", MidiOut_num ); if( !type_engine_import_mfun( env, func ) ) goto error; // add name() func = make_new_mfun( "string", "name", MidiOut_name ); if( !type_engine_import_mfun( env, func ) ) goto error; // add printerr() func = make_new_mfun( "void", "printerr", MidiOut_printerr ); func->add_arg( "int", "print_or_not" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add send() func = make_new_mfun( "int", "send", MidiOut_send ); func->add_arg( "MidiMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable MidiOut_offset_data = type_engine_import_mvar( env, "int", "@MidiOut_data", FALSE ); if( MidiOut_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } // static static t_CKUINT HidIn_offset_data = 0; static t_CKUINT HidMsg_offset_device_type = 0; static t_CKUINT HidMsg_offset_device_num = 0; static t_CKUINT HidMsg_offset_type = 0; static t_CKUINT HidMsg_offset_which = 0; static t_CKUINT HidMsg_offset_idata = 0; static t_CKUINT HidMsg_offset_fdata = 0; static t_CKUINT HidMsg_offset_when = 0; static t_CKUINT HidMsg_offset_deltax = 0; static t_CKUINT HidMsg_offset_deltay = 0; static t_CKUINT HidMsg_offset_axis_position = 0; // deprecated static t_CKUINT HidMsg_offset_axis_position2 = 0; static t_CKUINT HidMsg_offset_scaled_axis_position = 0; // deprecated static t_CKUINT HidMsg_offset_hat_position = 0; static t_CKUINT HidMsg_offset_cursorx = 0; static t_CKUINT HidMsg_offset_cursory = 0; static t_CKUINT HidMsg_offset_scaledcursorx = 0; static t_CKUINT HidMsg_offset_scaledcursory = 0; static t_CKUINT HidMsg_offset_x = 0; static t_CKUINT HidMsg_offset_y = 0; static t_CKUINT HidMsg_offset_z = 0; static t_CKUINT HidMsg_offset_ascii = 0; static t_CKUINT HidMsg_offset_key = 0; static t_CKUINT HidOut_offset_data = 0; //----------------------------------------------------------------------------- // name: init_class_HID() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_HID( Chuck_Env * env ) { Chuck_DL_Func * func = NULL; // init base class if( !type_engine_import_class_begin( env, "HidMsg", "Object", env->global(), NULL, NULL ) ) return FALSE; // add member variable HidMsg_offset_device_type = type_engine_import_mvar( env, "int", "deviceType", FALSE ); if( HidMsg_offset_device_type == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_device_num = type_engine_import_mvar( env, "int", "deviceNum", FALSE ); if( HidMsg_offset_device_num == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_type = type_engine_import_mvar( env, "int", "type", FALSE ); if( HidMsg_offset_type == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_which = type_engine_import_mvar( env, "int", "which", FALSE ); if( HidMsg_offset_which == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_idata = type_engine_import_mvar( env, "int", "idata", FALSE ); if( HidMsg_offset_idata == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_fdata = type_engine_import_mvar( env, "float", "fdata", FALSE ); if( HidMsg_offset_fdata == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_when = type_engine_import_mvar( env, "time", "when", FALSE ); if( HidMsg_offset_when == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_deltax = type_engine_import_mvar( env, "int", "deltaX", FALSE ); if( HidMsg_offset_deltax == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_deltay = type_engine_import_mvar( env, "int", "deltaY", FALSE ); if( HidMsg_offset_deltay == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_cursorx = type_engine_import_mvar( env, "int", "cursorX", FALSE ); if( HidMsg_offset_cursorx == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_cursory = type_engine_import_mvar( env, "int", "cursorY", FALSE ); if( HidMsg_offset_cursory == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_scaledcursorx = type_engine_import_mvar( env, "float", "scaledCursorX", FALSE ); if( HidMsg_offset_scaledcursorx == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_scaledcursory = type_engine_import_mvar( env, "float", "scaledCursorY", FALSE ); if( HidMsg_offset_scaledcursory == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_x = type_engine_import_mvar( env, "int", "x", FALSE ); if( HidMsg_offset_x == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_y = type_engine_import_mvar( env, "int", "y", FALSE ); if( HidMsg_offset_y == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_z = type_engine_import_mvar( env, "int", "z", FALSE ); if( HidMsg_offset_z == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_axis_position = type_engine_import_mvar( env, "int", "axis_position", FALSE ); if( HidMsg_offset_axis_position == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_axis_position2 = type_engine_import_mvar( env, "float", "axisPosition", FALSE ); if( HidMsg_offset_axis_position2 == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_hat_position = type_engine_import_mvar( env, "int", "hatPosition", FALSE ); if( HidMsg_offset_hat_position == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_ascii = type_engine_import_mvar( env, "int", "ascii", FALSE ); if( HidMsg_offset_ascii == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_key = type_engine_import_mvar( env, "int", "key", FALSE ); if( HidMsg_offset_key == CK_INVALID_OFFSET ) goto error; // add member variable HidMsg_offset_scaled_axis_position = type_engine_import_mvar( env, "float", "scaled_axis_position", FALSE ); if( HidMsg_offset_scaled_axis_position == CK_INVALID_OFFSET ) goto error; // add is_axis_motion() func = make_new_mfun( "int", "is_axis_motion", HidMsg_is_axis_motion ); // deprecated if( !type_engine_import_mfun( env, func ) ) goto error; // add isAxisMotion() func = make_new_mfun( "int", "isAxisMotion", HidMsg_is_axis_motion ); if( !type_engine_import_mfun( env, func ) ) goto error; // add is_button_down() func = make_new_mfun( "int", "is_button_down", HidMsg_is_button_down ); // deprecated if( !type_engine_import_mfun( env, func ) ) goto error; // add isButtonDown() func = make_new_mfun( "int", "isButtonDown", HidMsg_is_button_down ); if( !type_engine_import_mfun( env, func ) ) goto error; // add is_button_up() func = make_new_mfun( "int", "is_button_up", HidMsg_is_button_up ); // deprecated if( !type_engine_import_mfun( env, func ) ) goto error; // add isButtonUp() func = make_new_mfun( "int", "isButtonUp", HidMsg_is_button_up ); if( !type_engine_import_mfun( env, func ) ) goto error; // add is_mouse_motion() func = make_new_mfun( "int", "is_mouse_motion", HidMsg_is_mouse_motion ); // deprecated if( !type_engine_import_mfun( env, func ) ) goto error; // add isMouseMotion() func = make_new_mfun( "int", "isMouseMotion", HidMsg_is_mouse_motion ); if( !type_engine_import_mfun( env, func ) ) goto error; // add is_hat_motion() func = make_new_mfun( "int", "is_hat_motion", HidMsg_is_hat_motion ); // deprecated if( !type_engine_import_mfun( env, func ) ) goto error; // add isHatMotion() func = make_new_mfun( "int", "isHatMotion", HidMsg_is_hat_motion ); if( !type_engine_import_mfun( env, func ) ) goto error; // add isWheelMotion() func = make_new_mfun( "int", "isWheelMotion", HidMsg_is_wheel_motion ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); // register deprecate type_engine_register_deprecate( env, "HidIn", "Hid" ); // init base class Hid (copy of HidIn + constants) if( !type_engine_import_class_begin( env, "Hid", "Event", env->global(), HidIn_ctor, HidIn_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", HidIn_open ); func->add_arg( "int", "type" ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add openJoystick() func = make_new_mfun( "int", "openJoystick", HidIn_open_joystick ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add openMouse() func = make_new_mfun( "int", "openMouse", HidIn_open_mouse ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add openKeyboard() func = make_new_mfun( "int", "openKeyboard", HidIn_open_keyboard ); func->add_arg( "int", "num" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add openTiltSensor() func = make_new_mfun( "int", "openTiltSensor", HidIn_open_tiltsensor ); if( !type_engine_import_mfun( env, func ) ) goto error; // add good() func = make_new_mfun( "int", "good", HidIn_good ); if( !type_engine_import_mfun( env, func ) ) goto error; // add num() func = make_new_mfun( "int", "num", HidIn_num ); if( !type_engine_import_mfun( env, func ) ) goto error; // add name() func = make_new_mfun( "string", "name", HidIn_name ); if( !type_engine_import_mfun( env, func ) ) goto error; // add printerr() func = make_new_mfun( "void", "printerr", HidIn_printerr ); func->add_arg( "int", "print_or_not" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add recv() func = make_new_mfun( "int", "recv", HidIn_recv ); func->add_arg( "HidMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add read() func = make_new_mfun( "int", "read", HidIn_read ); func->add_arg( "int", "type" ); func->add_arg( "int", "which" ); func->add_arg( "HidMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add send() func = make_new_mfun( "int", "send", HidIn_send ); func->add_arg( "HidMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add can_wait() func = make_new_mfun( "int", "can_wait", HidIn_can_wait ); if( !type_engine_import_mfun( env, func ) ) goto error; // add readTiltSensor() func = make_new_sfun( "int[]", "readTiltSensor", HidIn_read_tilt_sensor ); if( !type_engine_import_sfun( env, func ) ) goto error; // add startCursorTrack() func = make_new_sfun( "int", "startCursorTrack", HidIn_start_cursor_track ); if( !type_engine_import_sfun( env, func ) ) goto error; // add stopCursorTrack() func = make_new_sfun( "int", "stopCursorTrack", HidIn_stop_cursor_track ); if( !type_engine_import_sfun( env, func ) ) goto error; // add member variable HidIn_offset_data = type_engine_import_mvar( env, "int", "@Hid_data", FALSE ); if( HidIn_offset_data == CK_INVALID_OFFSET ) goto error; // add static member variable joystick if( type_engine_import_svar( env, "int", "JOYSTICK", TRUE, ( t_CKUINT ) &CK_HID_DEV_JOYSTICK ) == FALSE ) goto error; // add static member variable keyboard if( type_engine_import_svar( env, "int", "KEYBOARD", TRUE, ( t_CKUINT ) &CK_HID_DEV_KEYBOARD ) == FALSE ) goto error; // add static member variable mouse if( type_engine_import_svar( env, "int", "MOUSE", TRUE, ( t_CKUINT ) &CK_HID_DEV_MOUSE ) == FALSE ) goto error; // add static member variable wii_remote if( type_engine_import_svar( env, "int", "WII_REMOTE", TRUE, ( t_CKUINT ) &CK_HID_DEV_WIIREMOTE ) == FALSE ) goto error; // add static member variable wii_remote if( type_engine_import_svar( env, "int", "TILT_SENSOR", TRUE, ( t_CKUINT ) &CK_HID_DEV_TILTSENSOR ) == FALSE ) goto error; // add static member variable tablet if( type_engine_import_svar( env, "int", "TABLET", TRUE, ( t_CKUINT ) &CK_HID_DEV_TABLET ) == FALSE ) goto error; // add static member variable axisMotion if( type_engine_import_svar( env, "int", "AXIS_MOTION", TRUE, ( t_CKUINT ) &CK_HID_JOYSTICK_AXIS ) == FALSE ) goto error; // add static member variable buttonDown if( type_engine_import_svar( env, "int", "BUTTON_DOWN", TRUE, ( t_CKUINT ) &CK_HID_BUTTON_DOWN ) == FALSE ) goto error; // add static member variable buttonUp if( type_engine_import_svar( env, "int", "BUTTON_UP", TRUE, ( t_CKUINT ) &CK_HID_BUTTON_UP ) == FALSE ) goto error; // add static member variable joystickHat if( type_engine_import_svar( env, "int", "JOYSTICK_HAT", TRUE, ( t_CKUINT ) &CK_HID_JOYSTICK_HAT ) == FALSE ) goto error; // add static member variable JOYSTICK_BALL if( type_engine_import_svar( env, "int", "JOYSTICK_BALL", TRUE, ( t_CKUINT ) &CK_HID_JOYSTICK_BALL ) == FALSE ) goto error; // add static member variable mouseMotion if( type_engine_import_svar( env, "int", "MOUSE_MOTION", TRUE, ( t_CKUINT ) &CK_HID_MOUSE_MOTION ) == FALSE ) goto error; // add static member variable mouseWheel if( type_engine_import_svar( env, "int", "MOUSE_WHEEL", TRUE, ( t_CKUINT ) &CK_HID_MOUSE_WHEEL ) == FALSE ) goto error; // add static member variable DEVICE_CONNECTED if( type_engine_import_svar( env, "int", "DEVICE_CONNECTED", TRUE, ( t_CKUINT ) &CK_HID_DEVICE_CONNECTED ) == FALSE ) goto error; // add static member variable DEVICE_DISCONNECTED if( type_engine_import_svar( env, "int", "DEVICE_DISCONNECTED", TRUE, ( t_CKUINT ) &CK_HID_DEVICE_DISCONNECTED ) == FALSE ) goto error; // add static member variable ACCELEROMETER if( type_engine_import_svar( env, "int", "ACCELEROMETER", TRUE, ( t_CKUINT ) &CK_HID_ACCELEROMETER ) == FALSE ) goto error; // add static member variable LED if( type_engine_import_svar( env, "int", "LED", TRUE, ( t_CKUINT ) &CK_HID_LED ) == FALSE ) goto error; // add static member variable LED if( type_engine_import_svar( env, "int", "FORCE_FEEDBACK", TRUE, ( t_CKUINT ) &CK_HID_FORCE_FEEDBACK ) == FALSE ) goto error; // end the class import type_engine_import_class_end( env ); /* // init base class if( !type_engine_import_class_begin( env, "HidOut", "Object", env->global(), HidOut_ctor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", HidOut_open ); func->add_arg( "int", "port" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add good() func = make_new_mfun( "int", "good", HidOut_good ); if( !type_engine_import_mfun( env, func ) ) goto error; // add num() func = make_new_mfun( "int", "num", HidOut_num ); if( !type_engine_import_mfun( env, func ) ) goto error; // add name() func = make_new_mfun( "string", "name", HidOut_name ); if( !type_engine_import_mfun( env, func ) ) goto error; // add printerr() func = make_new_mfun( "void", "printerr", HidOut_printerr ); func->add_arg( "int", "print_or_not" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add send() func = make_new_mfun( "int", "send", HidOut_send ); func->add_arg( "HidMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable HidOut_offset_data = type_engine_import_mvar( env, "int", "@HidOut_data", FALSE ); if( HidOut_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); */ return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } // static static t_CKUINT MidiRW_offset_data = 0; static t_CKUINT MidiMsgOut_offset_data = 0; static t_CKUINT MidiMsgIn_offset_data = 0; //----------------------------------------------------------------------------- // name: init_class_MidiRW() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_MidiRW( Chuck_Env * env ) { Chuck_DL_Func * func = NULL; // init base class if( !type_engine_import_class_begin( env, "MidiRW", "Object", env->global(), MidiRW_ctor, MidiRW_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiRW_open ); func->add_arg( "string", "filename" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add close() func = make_new_mfun( "int", "close", MidiRW_close ); if( !type_engine_import_mfun( env, func ) ) goto error; // add write() func = make_new_mfun( "int", "write", MidiRW_write ); func->add_arg( "MidiMsg", "msg" ); func->add_arg( "time", "t" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add read() func = make_new_mfun( "int", "read", MidiRW_read ); func->add_arg( "MidiMsg", "msg" ); //func->add_arg( "time", "t" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable MidiRW_offset_data = type_engine_import_mvar( env, "int", "@MidiRW_data", FALSE ); if( MidiRW_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "MidiMsgOut", "Object", env->global(), MidiMsgOut_ctor, MidiMsgOut_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiMsgOut_open ); func->add_arg( "string", "filename" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add close() func = make_new_mfun( "int", "close", MidiMsgOut_close ); if( !type_engine_import_mfun( env, func ) ) goto error; // add write() func = make_new_mfun( "int", "write", MidiMsgOut_write ); func->add_arg( "MidiMsg", "msg" ); func->add_arg( "time", "t" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable MidiMsgOut_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgOut_data", FALSE ); if( MidiMsgOut_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "MidiMsgIn", "Object", env->global(), MidiMsgIn_ctor, MidiMsgIn_dtor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiMsgIn_open ); func->add_arg( "string", "filename" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add close() func = make_new_mfun( "int", "close", MidiMsgIn_close ); if( !type_engine_import_mfun( env, func ) ) goto error; // add read() func = make_new_mfun( "int", "read", MidiMsgIn_read ); func->add_arg( "MidiMsg", "msg" ); //func->add_arg( "time", "t" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable MidiMsgIn_offset_data = type_engine_import_mvar( env, "int", "@MidiMsgIn_data", FALSE ); if( MidiMsgIn_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // initialize // HidInManager::init(); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } /*// static static t_CKUINT SkiniIn_offset_data = 0; static t_CKUINT SkiniOut_offset_data = 0; static t_CKUINT SkiniMsg_offset_type = 0; static t_CKUINT SkiniMsg_offset_time = 0; static t_CKUINT SkiniMsg_offset_channel = 0; static t_CKUINT SkiniMsg_offset_data1 = 0; static t_CKUINT SkiniMsg_offset_data2 = 0; //----------------------------------------------------------------------------- // name: init_class_Skini() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_class_Skini( Chuck_Env * env ) { Chuck_DL_Func * func = NULL; // init base class if( !type_engine_import_class_begin( env, "SkiniMsg", "Object", env->global(), NULL ) ) return FALSE; // add member variable SkiniMsg_offset_type = type_engine_import_mvar( env, "int", "type", FALSE ); if( SkiniMsg_offset_type == CK_INVALID_OFFSET ) goto error; // add member variable SkiniMsg_offset_time = type_engine_import_mvar( env, "float", "time", FALSE ); if( SkiniMsg_offset_time == CK_INVALID_OFFSET ) goto error; // add member variable SkiniMsg_offset_channel = type_engine_import_mvar( env, "int", "channel", FALSE ); if( SkiniMsg_offset_channel == CK_INVALID_OFFSET ) goto error; // add member variable SkiniMsg_offset_data1 = type_engine_import_mvar( env, "float", "data1", FALSE ); if( SkiniMsg_offset_data1 == CK_INVALID_OFFSET ) goto error; // add member variable SkiniMsg_offset_data2 = type_engine_import_mvar( env, "float", "data2", FALSE ); if( SkiniMsg_offset_data2 == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "SkiniIn", "event", env->global(), SkiniIn_ctor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", SkiniIn_open ); func->add_arg( "const char *", "filename" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add recv() func = make_new_mfun( "int", "recv", SkiniIn_recv ); func->add_arg( "SkiniMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable SkiniIn_offset_data = type_engine_import_mvar( env, "int", "@SkiniIn_data", FALSE ); if( SkiniIn_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // init base class if( !type_engine_import_class_begin( env, "SkiniOut", "Object", env->global(), SkiniOut_ctor ) ) return FALSE; // add open() func = make_new_mfun( "int", "open", MidiOut_open ); func->add_arg( "const char *", "filename" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add send() func = make_new_mfun( "int", "send", SkiniOut_send ); func->add_arg( "SkiniMsg", "msg" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable SkiniOut_offset_data = type_engine_import_mvar( env, "int", "@SkiniOut_data", FALSE ); if( SkiniOut_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } */ // Object ctor CK_DLL_CTOR( object_ctor ) { // fprintf( stderr, "object ctor\n" ); } // Object dtor CK_DLL_DTOR( object_dtor ) { // fprintf( stderr, "object dtor\n" ); } // setTestID CK_DLL_MFUN( object_setTestID ) { fprintf( stderr, "object set test id\n" ); t_CKINT v = GET_NEXT_INT(ARGS); OBJ_MEMBER_INT(SELF, object_offset_m_testID) = v; RETURN->v_int = v; } // getTestID CK_DLL_MFUN( object_getTestID ) { fprintf( stderr, "object get test id\n" ); RETURN->v_int = OBJ_MEMBER_INT(SELF, object_offset_m_testID); } // setTestID CK_DLL_MFUN( ugen_setTestID ) { fprintf( stderr, "ugen set test id\n" ); t_CKINT v = GET_NEXT_INT(ARGS); OBJ_MEMBER_INT(SELF, object_offset_m_testID) = v; RETURN->v_int = v; } // getTestID CK_DLL_MFUN( ugen_getTestID ) { fprintf( stderr, "ugen get test id\n" ); RETURN->v_int = OBJ_MEMBER_INT(SELF, object_offset_m_testID); } // getTest CK_DLL_SFUN( object_testStatic ) { t_CKFLOAT v = GET_NEXT_FLOAT(ARGS); fprintf( stderr, "testStatic %f\n", v ); } CK_DLL_CTOR( ugen_ctor ) { } CK_DLL_DTOR( ugen_dtor ) { // get as ugen // Chuck_UGen * ugen = (Chuck_UGen *)SELF; } CK_DLL_MFUN( ugen_op ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // get arg t_CKINT op = GET_CK_INT( ARGS ); // set op ugen->m_op = op; // set return RETURN->v_int = ugen->m_op; // for multiple channels Chuck_DL_Return ret; for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) ugen_op( ugen->m_multi_chan[i], ARGS, &ret, SHRED ); } CK_DLL_MFUN( ugen_cget_op ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // set return RETURN->v_int = ugen->m_op; } CK_DLL_MFUN( ugen_last ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // set return RETURN->v_float = (t_CKFLOAT)ugen->m_last; } CK_DLL_MFUN( ugen_next ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // get arg t_CKFLOAT next = GET_CK_FLOAT( ARGS ); // set op ugen->m_next = (SAMPLE)next; ugen->m_use_next = TRUE; // set return RETURN->v_float = (t_CKFLOAT)ugen->m_next; // for multiple channels Chuck_DL_Return ret; for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) ugen_next( ugen->m_multi_chan[i], ARGS, &ret, SHRED ); } CK_DLL_MFUN( ugen_cget_next ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // set return RETURN->v_float = ugen->m_use_next ? (t_CKFLOAT)ugen->m_next : 0.0f; } CK_DLL_MFUN( ugen_gain ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // get arg t_CKFLOAT gain = GET_CK_FLOAT( ARGS ); // set op ugen->m_gain = (SAMPLE)gain; // set return RETURN->v_float = (t_CKFLOAT)ugen->m_gain; // for multiple channels Chuck_DL_Return ret; for( t_CKUINT i = 0; i < ugen->m_multi_chan_size; i++ ) ugen_gain( ugen->m_multi_chan[i], ARGS, &ret, SHRED ); } CK_DLL_MFUN( ugen_cget_gain ) { // get as ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // set return RETURN->v_float = (t_CKFLOAT)ugen->m_gain; } CK_DLL_CTRL( ugen_numChannels ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // error EM_error3( "setting .numChannels is not yet supported (use the command line)..." ); } CK_DLL_CGET( ugen_cget_numChannels ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // return RETURN->v_int = ugen->m_multi_chan_size == 0 ? 1 : ugen->m_multi_chan_size; } CK_DLL_CTRL( ugen_chan ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKINT num = GET_NEXT_INT(ARGS); // check if( !ugen->m_multi_chan_size && num == 0 ) RETURN->v_object = ugen; else if( num >= 0 && num < ugen->m_multi_chan_size ) RETURN->v_object = ugen->m_multi_chan[num]; else RETURN->v_object = NULL; } CK_DLL_CTRL( ugen_connected ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; Chuck_UGen * right = (Chuck_UGen *)GET_NEXT_OBJECT(ARGS); // sanity t_CKINT ret = FALSE; if( !right ) { ret = FALSE; } else { ret = right->is_connected_from( ugen ); } RETURN->v_int = ret; } CK_DLL_CTOR( event_ctor ) { // OBJ_MEMBER_INT(SELF, event_offset_data) = (t_CKUINT)new Data_Event; // Chuck_Event * event = (Chuck_Event *)SELF; } CK_DLL_DTOR( event_dtor ) { // delete (Data_Event *)OBJ_MEMBER_INT(SELF, event_offset_data); } CK_DLL_MFUN( event_signal ) { Chuck_Event * d = (Chuck_Event *)SELF; d->signal(); } CK_DLL_MFUN( event_broadcast ) { Chuck_Event * d = (Chuck_Event *)SELF; d->broadcast(); } CK_DLL_MFUN( event_wait ) { // Chuck_Event * d = (Chuck_Event *)SELF; assert( FALSE ); } CK_DLL_MFUN( event_can_wait ) { RETURN->v_int = TRUE; } //----------------------------------------------------------------------------- // Shred API //----------------------------------------------------------------------------- //CK_DLL_CTOR( shred_ctor ); //CK_DLL_DTOR( shred_dtor ); // CK_DLL_MFUN( shred_exit ) { Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; // end the shred derhs->is_done = TRUE; derhs->is_running = FALSE; // return; // thanks } CK_DLL_MFUN( shred_clone ) { } CK_DLL_MFUN( shred_id ) { Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; // return the id RETURN->v_int = derhs->xid; } CK_DLL_MFUN( shred_yield ) { Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; Chuck_VM * vm = derhs->vm_ref; // suspend derhs->is_running = FALSE; // reshredule vm->shreduler()->shredule( derhs, derhs->now ); } CK_DLL_MFUN( shred_numArgs ) { Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; // get the number of arguments RETURN->v_int = derhs->args.size(); } CK_DLL_MFUN( shred_getArg ) { Chuck_VM_Shred * derhs = (Chuck_VM_Shred *)SELF; // get index t_CKINT i = GET_NEXT_INT(ARGS); // total t_CKINT num = derhs->args.size(); Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = ( i < num ? derhs->args[i] : "" ); RETURN->v_string = str; } CK_DLL_MFUN( string_length ) { Chuck_String * s = (Chuck_String *)SELF; RETURN->v_int = s->str.length(); } CK_DLL_MFUN( string_upper ) { Chuck_String * s = (Chuck_String *)SELF; Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = toupper( s->str ); RETURN->v_string = str; } CK_DLL_MFUN( string_lower ) { Chuck_String * s = (Chuck_String *)SELF; Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = tolower( s->str ); RETURN->v_string = str; } CK_DLL_MFUN( string_ltrim ) { Chuck_String * s = (Chuck_String *)SELF; Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = ltrim( s->str ); RETURN->v_string = str; } CK_DLL_MFUN( string_rtrim ) { Chuck_String * s = (Chuck_String *)SELF; Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = rtrim( s->str ); RETURN->v_string = str; } CK_DLL_MFUN( string_trim ) { Chuck_String * s = (Chuck_String *)SELF; Chuck_String * str = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); str->str = trim( s->str ); RETURN->v_string = str; } /* CK_DLL_MFUN( string_set_at ) { Chuck_String * s = (Chuck_String *)SELF; t_CKINT c = GET_CK_INT( RETURN->v_int = s->str.length(); } CK_DLL_MFUN( string_get_at ) { Chuck_String * s = (Chuck_String *)SELF; RETURN->v_int = s->str.length(); } */ // array.size() CK_DLL_MFUN( array_size ) { Chuck_Array * array = (Chuck_Array *)SELF; RETURN->v_int = array->size(); } // array.clear() CK_DLL_MFUN( array_clear ) { Chuck_Array * array = (Chuck_Array *)SELF; array->clear(); } // array.cap() CK_DLL_MFUN( array_set_capacity ) { Chuck_Array * array = (Chuck_Array *)SELF; t_CKINT capacity = GET_NEXT_INT(ARGS); if( capacity < 0 ) { // TODO: make this exception fprintf( stderr, "[chuck](via array): attempt to set negative array capacity!\n" ); RETURN->v_int = 0; } else { array->set_capacity( capacity ); RETURN->v_int = array->capacity(); } } // array.cap() CK_DLL_MFUN( array_get_capacity ) { Chuck_Array * array = (Chuck_Array *)SELF; RETURN->v_int = array->capacity(); } // array.find() CK_DLL_MFUN( array_find ) { Chuck_Array * array = (Chuck_Array *)SELF; Chuck_String * name = GET_NEXT_STRING( ARGS ); RETURN->v_int = array->find( name->str ); } // array.erase() CK_DLL_MFUN( array_erase ) { Chuck_Array * array = (Chuck_Array *)SELF; Chuck_String * name = GET_NEXT_STRING( ARGS ); RETURN->v_int = array->erase( name->str ); } // array.push_back() CK_DLL_MFUN( array_push_back ) { Chuck_Array * array = (Chuck_Array *)SELF; if( array->data_type_size() == CHUCK_ARRAY4_DATASIZE ) RETURN->v_int = ((Chuck_Array4 *)array)->push_back( GET_NEXT_UINT( ARGS ) ); else RETURN->v_float = ((Chuck_Array8 *)array)->push_back( GET_NEXT_FLOAT( ARGS ) ); } // array.pop_back() CK_DLL_MFUN( array_pop_back ) { Chuck_Array * array = (Chuck_Array *)SELF; if( array->data_type_size() == CHUCK_ARRAY4_DATASIZE ) RETURN->v_int = ((Chuck_Array4 *)array)->pop_back( ); else RETURN->v_float = ((Chuck_Array8 *)array)->pop_back( ); } //----------------------------------------------------------------------------- // MidiIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiIn_ctor ) { MidiIn * min = new MidiIn; min->SELF = SELF; OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = (t_CKINT)min; } CK_DLL_DTOR( MidiIn_dtor ) { delete (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); OBJ_MEMBER_INT(SELF, MidiIn_offset_data) = 0; } CK_DLL_MFUN( MidiIn_open ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); t_CKINT port = GET_CK_INT(ARGS); RETURN->v_int = min->open( port ); } CK_DLL_MFUN( MidiIn_good ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); RETURN->v_int = (t_CKINT)min->good(); } CK_DLL_MFUN( MidiIn_num ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); RETURN->v_int = min->num(); } CK_DLL_MFUN( MidiIn_printerr ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); t_CKINT print_or_not = GET_CK_INT(ARGS); min->set_suppress( !print_or_not ); } CK_DLL_MFUN( MidiIn_name ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); // TODO: memory leak, please fix, Thanks. Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); // only if valid if( min->good() ) a->str = min->min->getPortName( min->num() ); RETURN->v_string = a; } CK_DLL_MFUN( MidiIn_recv ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); MidiMsg the_msg; RETURN->v_int = min->recv( &the_msg ); if( RETURN->v_int ) { OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; } } CK_DLL_MFUN( MidiIn_can_wait ) { MidiIn * min = (MidiIn *)OBJ_MEMBER_INT(SELF, MidiIn_offset_data); RETURN->v_int = min->empty(); } //----------------------------------------------------------------------------- // MidiOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiOut_ctor ) { OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = (t_CKUINT)new MidiOut; } CK_DLL_DTOR( MidiOut_dtor ) { delete (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); OBJ_MEMBER_INT(SELF, MidiOut_offset_data) = 0; } CK_DLL_MFUN( MidiOut_open ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); t_CKINT port = GET_CK_INT(ARGS); RETURN->v_int = mout->open( port ); } CK_DLL_MFUN( MidiOut_good ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); RETURN->v_int = (t_CKINT)mout->good(); } CK_DLL_MFUN( MidiOut_num ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); RETURN->v_int = mout->num(); } CK_DLL_MFUN( MidiOut_name ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); // TODO: memory leak, please fix, Thanks. Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); // only if valid if( mout->good() ) a->str = mout->mout->getPortName( mout->num() ); RETURN->v_string = a; } CK_DLL_MFUN( MidiOut_printerr ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); t_CKINT print_or_not = GET_CK_INT(ARGS); mout->set_suppress( !print_or_not ); } CK_DLL_MFUN( MidiOut_send ) { MidiOut * mout = (MidiOut *)OBJ_MEMBER_INT(SELF, MidiOut_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); MidiMsg the_msg; the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); RETURN->v_int = mout->send( &the_msg ); } //----------------------------------------------------------------------------- // HidMsg API //----------------------------------------------------------------------------- CK_DLL_MFUN( HidMsg_is_axis_motion ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_JOYSTICK_AXIS ? 1 : 0 ); } CK_DLL_MFUN( HidMsg_is_button_down ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_BUTTON_DOWN ? 1 : 0 ); } CK_DLL_MFUN( HidMsg_is_button_up ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_BUTTON_UP ? 1 : 0 ); } CK_DLL_MFUN( HidMsg_is_mouse_motion ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_MOUSE_MOTION ? 1 : 0 ); } CK_DLL_MFUN( HidMsg_is_hat_motion ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_JOYSTICK_HAT ? 1 : 0 ); } CK_DLL_MFUN( HidMsg_is_wheel_motion ) { RETURN->v_int = ( ( t_CKINT ) OBJ_MEMBER_INT( SELF, HidMsg_offset_type ) == CK_HID_MOUSE_WHEEL ? 1 : 0 ); } //----------------------------------------------------------------------------- // HidIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( HidIn_ctor ) { HidIn * min = new HidIn; min->SELF = SELF; OBJ_MEMBER_INT(SELF, HidIn_offset_data) = (t_CKINT)min; } CK_DLL_DTOR( HidIn_dtor ) { delete (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); OBJ_MEMBER_INT(SELF, HidIn_offset_data) = 0; } CK_DLL_MFUN( HidIn_open ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT type = GET_NEXT_INT(ARGS); t_CKINT num = GET_NEXT_INT(ARGS); RETURN->v_int = min->open( type, num ); } CK_DLL_MFUN( HidIn_open_joystick ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT num = GET_NEXT_INT(ARGS); RETURN->v_int = min->open( CK_HID_DEV_JOYSTICK, num ); } CK_DLL_MFUN( HidIn_open_mouse ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT num = GET_NEXT_INT(ARGS); RETURN->v_int = min->open( CK_HID_DEV_MOUSE, num ); } CK_DLL_MFUN( HidIn_open_keyboard ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT num = GET_NEXT_INT(ARGS); RETURN->v_int = min->open( CK_HID_DEV_KEYBOARD, num ); } CK_DLL_MFUN( HidIn_open_tiltsensor ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); RETURN->v_int = min->open( CK_HID_DEV_TILTSENSOR, 0 ); } CK_DLL_MFUN( HidIn_good ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); RETURN->v_int = (t_CKINT)min->good(); } CK_DLL_MFUN( HidIn_num ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); RETURN->v_int = min->num(); } CK_DLL_MFUN( HidIn_printerr ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT print_or_not = GET_CK_INT(ARGS); min->set_suppress( !print_or_not ); } CK_DLL_MFUN( HidIn_name ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); // TODO: memory leak, please fix, Thanks. // Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); // only if valid // if( min->good() ) // a->str = min->phin->getPortName( min->num() ); // TODO: is null problem? RETURN->v_string = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); RETURN->v_string->str = min->name(); } CK_DLL_MFUN( HidIn_recv ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); HidMsg the_msg; RETURN->v_int = min->recv( &the_msg ); if( RETURN->v_int ) { OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0]; // mouse motion specific member variables OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1]; // axis motion specific member variables OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0]; // hat motion specific variables OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0]; // keyboard specific variables OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2]; // accelerometer (tilt sensor, wii remote) specific members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2]; } } CK_DLL_MFUN( HidIn_read ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); t_CKINT type = GET_NEXT_INT(ARGS); t_CKINT num = GET_NEXT_INT(ARGS); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); HidMsg the_msg; RETURN->v_int = min->read( type, num, &the_msg ); if( RETURN->v_int ) { OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_type) = the_msg.device_type; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_device_num) = the_msg.device_num; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_type) = the_msg.type; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_which) = the_msg.eid; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_idata) = the_msg.idata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_fdata) = the_msg.fdata[0]; // mouse motion specific member members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltax) = the_msg.idata[0]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_deltay) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursorx) = the_msg.idata[2]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_cursory) = the_msg.idata[3]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursorx) = the_msg.fdata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaledcursory) = the_msg.fdata[1]; // joystick axis specific member members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_axis_position) = the_msg.idata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_scaled_axis_position) = the_msg.fdata[0]; OBJ_MEMBER_FLOAT(fake_msg, HidMsg_offset_axis_position2) = the_msg.fdata[0]; // joystick hat specific member members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_hat_position) = the_msg.idata[0]; // keyboard specific members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_key) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_ascii) = the_msg.idata[2]; // accelerometer (tilt sensor, wii remote) specific members OBJ_MEMBER_INT(fake_msg, HidMsg_offset_x) = the_msg.idata[0]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_y) = the_msg.idata[1]; OBJ_MEMBER_INT(fake_msg, HidMsg_offset_z) = the_msg.idata[2]; } } CK_DLL_MFUN( HidIn_send ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); HidMsg the_msg; the_msg.device_type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_type ); the_msg.device_num = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_device_num ); the_msg.type = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_type ); the_msg.eid = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_which ); the_msg.idata[0] = OBJ_MEMBER_INT( fake_msg, HidMsg_offset_idata ); RETURN->v_int = min->send( &the_msg ); } CK_DLL_MFUN( HidIn_can_wait ) { HidIn * min = (HidIn *)OBJ_MEMBER_INT(SELF, HidIn_offset_data); RETURN->v_int = min->empty(); } CK_DLL_SFUN( HidIn_read_tilt_sensor ) { static HidIn * hi; static t_CKBOOL hi_good = TRUE; Chuck_Array4 * array = new Chuck_Array4( FALSE, 3 ); array->set( 0, 0 ); array->set( 1, 0 ); array->set( 2, 0 ); RETURN->v_object = array; if( hi_good == FALSE ) return; if( !hi ) { hi = new HidIn; if( !hi->open( CK_HID_DEV_TILTSENSOR, 0 ) ) { hi_good = FALSE; return; } } HidMsg msg; if( !hi->read( CK_HID_ACCELEROMETER, 0, &msg ) ) { return; } array->set( 0, msg.idata[0] ); array->set( 1, msg.idata[1] ); array->set( 2, msg.idata[2] ); } CK_DLL_SFUN( HidIn_start_cursor_track ) { RETURN->v_int = !Mouse_start_cursor_track(); } CK_DLL_SFUN( HidIn_stop_cursor_track ) { RETURN->v_int = !Mouse_stop_cursor_track(); } //----------------------------------------------------------------------------- // HidOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( HidOut_ctor ) { OBJ_MEMBER_INT(SELF, HidOut_offset_data) = (t_CKUINT)new HidOut; } CK_DLL_DTOR( HidOut_dtor ) { delete (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); OBJ_MEMBER_INT(SELF, HidOut_offset_data) = 0; } CK_DLL_MFUN( HidOut_open ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); t_CKINT num = GET_CK_INT(ARGS); RETURN->v_int = mout->open( num ); } CK_DLL_MFUN( HidOut_good ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); RETURN->v_int = (t_CKINT)mout->good(); } CK_DLL_MFUN( HidOut_num ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); RETURN->v_int = mout->num(); } CK_DLL_MFUN( HidOut_name ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); // TODO: memory leak, please fix, Thanks. Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); // only if valid // if( mout->good() ) // a->str = mout->mout->getPortName( mout->num() ); RETURN->v_string = a; } CK_DLL_MFUN( HidOut_printerr ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); t_CKINT print_or_not = GET_CK_INT(ARGS); mout->set_suppress( !print_or_not ); } CK_DLL_MFUN( HidOut_send ) { HidOut * mout = (HidOut *)OBJ_MEMBER_INT(SELF, HidOut_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); HidMsg the_msg; /* the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data1); the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data2); the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, HidMsg_offset_data3); */ RETURN->v_int = mout->send( &the_msg ); } //----------------------------------------------------------------------------- // MidiRW API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiRW_ctor ) { OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = (t_CKUINT)new MidiRW; } CK_DLL_DTOR( MidiRW_dtor ) { delete (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); OBJ_MEMBER_INT(SELF, MidiRW_offset_data) = 0; } CK_DLL_MFUN( MidiRW_open ) { MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = mrw->open( filename ); } CK_DLL_MFUN( MidiRW_close ) { MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); RETURN->v_int = mrw->close(); } CK_DLL_MFUN( MidiRW_read ) { MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); MidiMsg the_msg; t_CKTIME time = 0.0; RETURN->v_int = mrw->read( &the_msg, &time ); OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; } CK_DLL_MFUN( MidiRW_write ) { MidiRW * mrw = (MidiRW *)OBJ_MEMBER_INT(SELF, MidiRW_offset_data); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); t_CKTIME time = GET_NEXT_TIME(ARGS); MidiMsg the_msg; the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); RETURN->v_int = mrw->write( &the_msg, &time ); } //----------------------------------------------------------------------------- // MidiMsgOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiMsgOut_ctor ) { OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = (t_CKUINT)new MidiMsgOut; } CK_DLL_DTOR( MidiMsgOut_dtor ) { delete (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data) = 0; } CK_DLL_MFUN( MidiMsgOut_open ) { MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = mrw->open( filename ); } CK_DLL_MFUN( MidiMsgOut_close ) { MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); RETURN->v_int = mrw->close(); } CK_DLL_MFUN( MidiMsgOut_write ) { MidiMsgOut * mrw = (MidiMsgOut *)OBJ_MEMBER_INT(SELF, MidiMsgOut_offset_data); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); t_CKTIME time = GET_NEXT_TIME(ARGS); MidiMsg the_msg; the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1); the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2); the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3); RETURN->v_int = mrw->write( &the_msg, &time ); } //----------------------------------------------------------------------------- // MidiMsgIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiMsgIn_ctor ) { OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = (t_CKUINT)new MidiMsgIn; } CK_DLL_DTOR( MidiMsgIn_dtor ) { delete (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data) = 0; } CK_DLL_MFUN( MidiMsgIn_open ) { MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = mrw->open( filename ); } CK_DLL_MFUN( MidiMsgIn_close ) { MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); RETURN->v_int = mrw->close(); } CK_DLL_MFUN( MidiMsgIn_read ) { MidiMsgIn * mrw = (MidiMsgIn *)OBJ_MEMBER_INT(SELF, MidiMsgIn_offset_data); Chuck_Object * fake_msg = GET_NEXT_OBJECT(ARGS); MidiMsg the_msg; t_CKTIME time = 0.0; RETURN->v_int = mrw->read( &the_msg, &time ); OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data1) = the_msg.data[0]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data2) = the_msg.data[1]; OBJ_MEMBER_INT(fake_msg, MidiMsg_offset_data3) = the_msg.data[2]; OBJ_MEMBER_TIME(fake_msg, MidiMsg_offset_when) = time; } /*//----------------------------------------------------------------------------- // SkiniIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( SkiniIn_ctor ) { SkiniIn * skin = new SkiniIn; // skin->SELF = SELF; OBJ_MEMBER_INT(SELF, SkiniIn_offset_data) = (t_CKINT)skin; } CK_DLL_DTOR( SkiniIn_dtor ) { delete (SkiniIn *)OBJ_MEMBER_INT(SELF, SkiniIn_offset_data); } CK_DLL_MFUN( SkiniIn_open ) { SkiniIn * skin = (SkiniIn *)OBJ_MEMBER_INT(SELF, SkiniIn_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = skin->open( filename ); } CK_DLL_MFUN( SkiniIn_recv ) { SkiniIn * skin = (SkiniIn *)OBJ_MEMBER_INT(SELF, SkiniIn_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); SkiniMsg the_msg; RETURN->v_int = skin->recv( &the_msg ); if( RETURN->v_int ) { OBJ_MEMBER_INT( fake_msg, SkiniMsg_offset_type ) = the_msg.type; OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_time ) = the_msg.time; OBJ_MEMBER_INT( fake_msg, SkiniMsg_offset_channel ) = the_msg.channel; OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_data1 ) = the_msg.data1; OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_data2 ) = the_msg.data2; } } //----------------------------------------------------------------------------- // SkiniOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( SkiniOut_ctor ) { OBJ_MEMBER_INT(SELF, SkiniOut_offset_data) = (t_CKUINT)new SkiniOut; } CK_DLL_DTOR( SkiniOut_dtor ) { delete (SkiniOut *)OBJ_MEMBER_INT(SELF, SkiniOut_offset_data); } CK_DLL_MFUN( SkiniOut_open ) { SkiniOut * sout = (SkiniOut *)OBJ_MEMBER_INT(SELF, SkiniOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = sout->open( filename ); } CK_DLL_MFUN( SkiniOut_send ) { SkiniOut * sout = (SkiniOut *)OBJ_MEMBER_INT(SELF, SkiniOut_offset_data); Chuck_Object * fake_msg = GET_CK_OBJECT(ARGS); SkiniMsg the_msg; the_msg.type = OBJ_MEMBER_INT( fake_msg, SkiniMsg_offset_type ); the_msg.time = OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_time ); the_msg.channel = OBJ_MEMBER_INT( fake_msg, SkiniMsg_offset_channel ); the_msg.data1 = OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_data1 ); the_msg.data2 = OBJ_MEMBER_FLOAT( fake_msg, SkiniMsg_offset_data2 ); //the_msg.data[0] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, SkiniMsg_offset_data1); //the_msg.data[1] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, SkiniMsg_offset_data2); //the_msg.data[2] = (t_CKBYTE)OBJ_MEMBER_INT(fake_msg, SkiniMsg_offset_data3); RETURN->v_int = sout->send( &the_msg ); } */ /* //----------------------------------------------------------------------------- // name: lang_query() // desc: query entry point //----------------------------------------------------------------------------- DLL_QUERY lang_query( Chuck_DL_Query * QUERY ) { QUERY->setname( QUERY, "Lang" ); // class QUERY->begin_class( QUERY, "Object", "" ); // add ctor QUERY->add_ctor( QUERY, object_ctor ); // add dtor QUERY->add_dtor( QUERY, object_dtor ); // add setTestID QUERY->add_mfun( QUERY, object_setTestID, "void", "setTestID" ); QUERY->add_arg( QUERY, "int", "value" ); // add getTestID QUERY->add_mfun( QUERY, object_getTestID, "int", "getTestID" ); // add toString //! return string that represents the value of the object // QUERY->add_mfun( QUERY, object_toString, "string", "toString" ); // end class QUERY->end_class( QUERY ); return TRUE; } */ chuck-1.2.0.8.dfsg/src/chuck_lang.h0000644000175000017500000002347710600421722015412 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_lang.h // desc: chuck class library base // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: spring 2005 //----------------------------------------------------------------------------- #ifndef __CHUCK_LANG_H__ #define __CHUCK_LANG_H__ #include "chuck_def.h" #include "chuck_oo.h" #include "chuck_dl.h" #include // query DLL_QUERY lang_query( Chuck_DL_Query * QUERY ); // base class initialization t_CKBOOL init_class_object( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_ugen( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_event( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_shred( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_string( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_array( Chuck_Env * env, Chuck_Type * type ); t_CKBOOL init_class_Midi( Chuck_Env * env ); t_CKBOOL init_class_MidiRW( Chuck_Env * env ); t_CKBOOL init_class_HID( Chuck_Env * env ); //----------------------------------------------------------------------------- // object API //----------------------------------------------------------------------------- CK_DLL_CTOR( object_ctor ); CK_DLL_DTOR( object_dtor ); CK_DLL_MFUN( object_equals ); CK_DLL_MFUN( object_getType ); CK_DLL_MFUN( object_hashCode ); CK_DLL_MFUN( object_toString ); CK_DLL_MFUN( object_setTestID ); CK_DLL_MFUN( object_getTestID ); CK_DLL_MFUN( ugen_setTestID ); CK_DLL_MFUN( ugen_getTestID ); CK_DLL_SFUN( object_testStatic ); //----------------------------------------------------------------------------- // ugen API //----------------------------------------------------------------------------- CK_DLL_CTOR( ugen_ctor ); CK_DLL_DTOR( ugen_dtor ); CK_DLL_MFUN( ugen_op ); CK_DLL_MFUN( ugen_cget_op ); CK_DLL_MFUN( ugen_last ); CK_DLL_MFUN( ugen_cget_last ); CK_DLL_MFUN( ugen_next ); CK_DLL_MFUN( ugen_cget_next ); CK_DLL_MFUN( ugen_gain ); CK_DLL_MFUN( ugen_cget_gain ); CK_DLL_MFUN( ugen_numChannels ); CK_DLL_MFUN( ugen_cget_numChannels ); CK_DLL_MFUN( ugen_chan ); CK_DLL_MFUN( ugen_connected ); //----------------------------------------------------------------------------- // shred API //----------------------------------------------------------------------------- CK_DLL_CTOR( shred_ctor ); CK_DLL_DTOR( shred_dtor ); CK_DLL_MFUN( shred_exit ); CK_DLL_MFUN( shred_clone ); CK_DLL_MFUN( shred_id ); CK_DLL_MFUN( shred_yield ); CK_DLL_MFUN( shred_numArgs ); CK_DLL_MFUN( shred_getArg ); //----------------------------------------------------------------------------- // array API //----------------------------------------------------------------------------- CK_DLL_CTOR( array_ctor ); CK_DLL_DTOR( array_dtor ); CK_DLL_MFUN( array_set_capacity ); CK_DLL_MFUN( array_get_capacity ); CK_DLL_MFUN( array_size ); CK_DLL_MFUN( array_push_back ); CK_DLL_MFUN( array_pop_back ); CK_DLL_MFUN( array_push_front ); CK_DLL_MFUN( array_pop_font ); CK_DLL_MFUN( array_find ); CK_DLL_MFUN( array_erase ); CK_DLL_MFUN( array_clear ); //----------------------------------------------------------------------------- // event API //----------------------------------------------------------------------------- CK_DLL_CTOR( event_ctor ); CK_DLL_DTOR( event_dtor ); CK_DLL_MFUN( event_signal ); CK_DLL_MFUN( event_broadcast ); CK_DLL_MFUN( event_wait ); CK_DLL_MFUN( event_can_wait ); //----------------------------------------------------------------------------- // string API //----------------------------------------------------------------------------- CK_DLL_CTOR( string_ctor ); CK_DLL_DTOR( string_dtor ); CK_DLL_MFUN( string_length ); CK_DLL_MFUN( string_upper ); CK_DLL_MFUN( string_lower ); CK_DLL_MFUN( string_ltrim ); CK_DLL_MFUN( string_rtrim ); CK_DLL_MFUN( string_trim ); CK_DLL_MFUN( string_set_at ); CK_DLL_MFUN( string_get_at ); //----------------------------------------------------------------------------- // name: Data_Exception // desc: data for base Chuck Exception class //----------------------------------------------------------------------------- struct Data_Exception { public: Data_Exception(); ~Data_Exception(); public: }; //----------------------------------------------------------------------------- // exception API //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // MidiMsg API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiMsg_ctor ); //----------------------------------------------------------------------------- // MidiRW API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiRW_ctor ); CK_DLL_DTOR( MidiRW_dtor ); CK_DLL_MFUN( MidiRW_open ); CK_DLL_MFUN( MidiRW_close ); CK_DLL_MFUN( MidiRW_read ); CK_DLL_MFUN( MidiRW_write ); //----------------------------------------------------------------------------- // MidiMsgOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiMsgOut_ctor ); CK_DLL_DTOR( MidiMsgOut_dtor ); CK_DLL_MFUN( MidiMsgOut_open ); CK_DLL_MFUN( MidiMsgOut_close ); CK_DLL_MFUN( MidiMsgOut_write ); //----------------------------------------------------------------------------- // MidiMsgIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiMsgIn_ctor ); CK_DLL_DTOR( MidiMsgIn_dtor ); CK_DLL_MFUN( MidiMsgIn_open ); CK_DLL_MFUN( MidiMsgIn_close ); CK_DLL_MFUN( MidiMsgIn_read ); //----------------------------------------------------------------------------- // MidiIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiIn_ctor ); CK_DLL_DTOR( MidiIn_dtor ); CK_DLL_MFUN( MidiIn_open ); CK_DLL_MFUN( MidiIn_good ); CK_DLL_MFUN( MidiIn_num ); CK_DLL_MFUN( MidiIn_name ); CK_DLL_MFUN( MidiIn_printerr ); CK_DLL_MFUN( MidiIn_recv ); CK_DLL_MFUN( MidiIn_can_wait ); //----------------------------------------------------------------------------- // MidiOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( MidiOut_ctor ); CK_DLL_DTOR( MidiOut_dtor ); CK_DLL_MFUN( MidiOut_open ); CK_DLL_MFUN( MidiOut_good ); CK_DLL_MFUN( MidiOut_num ); CK_DLL_MFUN( MidiOut_name ); CK_DLL_MFUN( MidiOut_printerr ); CK_DLL_MFUN( MidiOut_send ); //----------------------------------------------------------------------------- // HidMsg API //----------------------------------------------------------------------------- CK_DLL_MFUN( HidMsg_is_axis_motion ); CK_DLL_MFUN( HidMsg_is_button_down ); CK_DLL_MFUN( HidMsg_is_button_up ); CK_DLL_MFUN( HidMsg_is_mouse_motion ); CK_DLL_MFUN( HidMsg_is_hat_motion ); CK_DLL_MFUN( HidMsg_is_wheel_motion ); //----------------------------------------------------------------------------- // HidIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( HidIn_ctor ); CK_DLL_DTOR( HidIn_dtor ); CK_DLL_MFUN( HidIn_open ); CK_DLL_MFUN( HidIn_open_joystick ); CK_DLL_MFUN( HidIn_open_mouse ); CK_DLL_MFUN( HidIn_open_keyboard ); CK_DLL_MFUN( HidIn_open_tiltsensor ); CK_DLL_MFUN( HidIn_good ); CK_DLL_MFUN( HidIn_num ); CK_DLL_MFUN( HidIn_name ); CK_DLL_MFUN( HidIn_printerr ); CK_DLL_MFUN( HidIn_recv ); CK_DLL_MFUN( HidIn_read ); CK_DLL_MFUN( HidIn_send ); CK_DLL_MFUN( HidIn_can_wait ); CK_DLL_SFUN( HidIn_read_tilt_sensor ); CK_DLL_SFUN( HidIn_start_cursor_track ); CK_DLL_SFUN( HidIn_stop_cursor_track ); //----------------------------------------------------------------------------- // HidOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( HidOut_ctor ); CK_DLL_DTOR( HidOut_dtor ); CK_DLL_MFUN( HidOut_open ); CK_DLL_MFUN( HidOut_good ); CK_DLL_MFUN( HidOut_num ); CK_DLL_MFUN( HidOut_name ); CK_DLL_MFUN( HidOut_printerr ); CK_DLL_MFUN( HidOut_send ); //----------------------------------------------------------------------------- // SkiniMMsg API //----------------------------------------------------------------------------- CK_DLL_CTOR( SkiniMsg_ctor ); //----------------------------------------------------------------------------- // SkiniIn API //----------------------------------------------------------------------------- CK_DLL_CTOR( SkiniIn_ctor ); CK_DLL_DTOR( SkiniIn_dtor ); CK_DLL_MFUN( SkiniIn_open ); CK_DLL_MFUN( SkiniIn_recv ); //----------------------------------------------------------------------------- // SkiniOut API //----------------------------------------------------------------------------- CK_DLL_CTOR( SkiniOut_ctor ); CK_DLL_DTOR( SkiniOut_dtor ); CK_DLL_MFUN( SkiniOut_open ); CK_DLL_MFUN( SkiniOut_send ); #endif chuck-1.2.0.8.dfsg/src/chuck_main.cpp0000644000175000017500000005406310600421722015743 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_main.cpp // desc: chuck entry point // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // additional contributors: // Ananya Misra (amisra@cs.princeton.edu) // Spencer Salazar (salazar@cs.princeton.edu) // date: version 1.1.x.x - Autumn 2002 // version 1.2.x.x - Autumn 2004 //----------------------------------------------------------------------------- #include #include #include #include "chuck_compile.h" #include "chuck_vm.h" #include "chuck_bbq.h" #include "chuck_errmsg.h" #include "chuck_lang.h" #include "chuck_otf.h" #include "chuck_shell.h" #include "chuck_console.h" #include "chuck_globals.h" #include "util_string.h" #include "util_thread.h" #include "util_network.h" #include "hidio_sdl.h" #include #ifndef __PLATFORM_WIN32__ #include #include #include #endif // global variables #if defined(__MACOSX_CORE__) t_CKINT g_priority = 80; t_CKINT g_priority_low = 60; #elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__) t_CKINT g_priority = THREAD_PRIORITY_HIGHEST; t_CKINT g_priority_low = THREAD_PRIORITY_HIGHEST; #else t_CKINT g_priority = 0x7fffffff; t_CKINT g_priority_low = 0x7fffffff; #endif // thread id for otf thread CHUCK_THREAD g_tid_otf = 0; // thread id for shell CHUCK_THREAD g_tid_shell = 0; // default destination host name char g_host[256] = "127.0.0.1"; //----------------------------------------------------------------------------- // name: signal_int() // desc: ... //----------------------------------------------------------------------------- extern "C" void signal_int( int sig_num ) { fprintf( stderr, "[chuck]: cleaning up...\n" ); if( g_vm ) { // get vm Chuck_VM * vm = g_vm; // flag the global one g_vm = NULL; // if not NULL if( vm ) { // stop vm->stop(); // detach all_detach(); } // things don't work so good on windows... #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) // pthread_kill( g_tid_otf, 2 ); if( g_tid_otf ) pthread_cancel( g_tid_otf ); if( g_tid_whatever ) pthread_cancel( g_tid_whatever ); // if( g_tid_otf ) usleep( 50000 ); SAFE_DELETE( vm ); SAFE_DELETE( g_compiler ); #else // close handle if( g_tid_otf ) CloseHandle( g_tid_otf ); #endif // ck_close( g_sock ); } #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) // pthread_join( g_tid_otf, NULL ); #endif exit(2); } //----------------------------------------------------------------------------- // name: next_power_2() // desc: ... // thanks: to Niklas Werner / music-dsp //----------------------------------------------------------------------------- t_CKUINT next_power_2( t_CKUINT n ) { t_CKUINT nn = n; for( ; n &= n-1; nn = n ); return nn * 2; } //----------------------------------------------------------------------------- // name: uh() // desc: ... //----------------------------------------------------------------------------- void uh( ) { // TODO: play white noise and/or sound effects srand( time( NULL ) ); while( true ) { int n = (int)(rand() / (float)RAND_MAX * poop_size); printf( "%s\n", poop[n] ); usleep( (unsigned long)(rand() / (float)RAND_MAX * 2000000) ); } } //----------------------------------------------------------------------------- // name: init_shell() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL init_shell( Chuck_Shell * shell, Chuck_Shell_UI * ui, Chuck_VM * vm ) { // initialize shell UI if( !ui->init() ) { fprintf( stderr, "[chuck]: error starting shell UI...\n" ); return FALSE; } // initialize if( !shell->init( vm, ui ) ) { fprintf( stderr, "[chuck]: error starting shell...\n" ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: get_count() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL get_count( const char * arg, t_CKUINT * out ) { // no comment if( !strncmp( arg, "--", 2 ) ) arg += 2; else if( !strncmp( arg, "-", 1 ) ) arg += 1; else return FALSE; // end of string if( *arg == '\0' ) return FALSE; // not digit if( *arg < '0' || *arg > '9' ) return FALSE; // number *out = (t_CKUINT)atoi( arg ); return TRUE; } //----------------------------------------------------------------------------- // name: version() // desc: ... //----------------------------------------------------------------------------- void version() { fprintf( stderr, "\n" ); fprintf( stderr, "chuck version: %s\n", CK_VERSION ); #if defined(__PLATFORM_WIN32__) fprintf( stderr, " exe target: microsoft win32\n" ); #elif defined(__WINDOWS_DS__) fprintf( stderr, " exe target: microsoft win32 + cygwin\n" ); #elif defined(__LINUX_ALSA__) fprintf( stderr, " exe target: linux (alsa)\n" ); #elif defined(__LINUX_OSS__) fprintf( stderr, " exe target: linux (oss)\n" ); #elif defined(__LINUX_JACK__) fprintf( stderr, " exe target: linux (jack)\n" ); #elif defined(__MACOSX_UB__) fprintf( stderr, " exe target: mac os x : universal binary\n" ); #elif defined(__MACOSX_CORE__) && defined(__LITTLE_ENDIAN__) fprintf( stderr, " exe target: mac os x : intel\n" ); #elif defined(__MACOSX_CORE__) fprintf( stderr, " exe target: mac os x : powerpc\n" ); #else fprintf( stderr, " exe target: uh... unknown\n" ); #endif fprintf( stderr, " http://chuck.cs.princeton.edu/\n\n" ); } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- void usage() { fprintf( stderr, "usage: chuck --[options|commands] [+-=^] file1 file2 file3 ...\n" ); fprintf( stderr, " [options] = halt|loop|audio|silent|dump|nodump|server|about|\n" ); fprintf( stderr, " srate|bufsize|bufnum|dac|adc|\n" ); fprintf( stderr, " remote|port|verbose|probe|\n" ); fprintf( stderr, " channels|out|in|shell|empty|level|\n" ); fprintf( stderr, " blocking|callback|deprecate:{stop|warn|ignore}\n" ); fprintf( stderr, " [commands] = add|remove|replace|removeall|status|time|kill\n" ); fprintf( stderr, " [+-=^] = shortcuts for add, remove, replace, status\n" ); version(); } //----------------------------------------------------------------------------- // name: main() // desc: entry point //----------------------------------------------------------------------------- int main( int argc, char ** argv ) { Chuck_Compiler * compiler = NULL; Chuck_VM * vm = NULL; Chuck_VM_Code * code = NULL; Chuck_VM_Shred * shred = NULL; t_CKBOOL enable_audio = TRUE; t_CKBOOL vm_halt = TRUE; t_CKUINT srate = SAMPLING_RATE_DEFAULT; t_CKUINT buffer_size = BUFFER_SIZE_DEFAULT; t_CKUINT num_buffers = NUM_BUFFERS_DEFAULT; t_CKUINT dac = 0; t_CKUINT adc = 0; t_CKUINT dac_chans = 2; t_CKUINT adc_chans = 2; t_CKBOOL dump = FALSE; t_CKBOOL probe = FALSE; t_CKBOOL set_priority = FALSE; t_CKBOOL auto_depend = FALSE; t_CKBOOL block = FALSE; t_CKBOOL enable_shell = FALSE; t_CKBOOL no_vm = FALSE; t_CKBOOL load_hid = FALSE; t_CKBOOL enable_server = TRUE; t_CKBOOL do_watchdog = TRUE; t_CKINT log_level = CK_LOG_CORE; t_CKINT deprecate_level = 1; // warn string filename = ""; vector args; #if defined(__MACOSX_CORE__) do_watchdog = TRUE; #elif defined(__PLATFORM_WIN32__) && !defined(__WINDOWS_PTHREAD__) do_watchdog = TRUE; #else do_watchdog = FALSE; #endif t_CKUINT files = 0; t_CKUINT count = 1; t_CKINT i; // set log level EM_setlog( log_level ); // parse command line args for( i = 1; i < argc; i++ ) { if( argv[i][0] == '-' || argv[i][0] == '+' || argv[i][0] == '=' || argv[i][0] == '^' || argv[i][0] == '@' ) { if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d") || !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d") ) continue; else if( get_count( argv[i], &count ) ) continue; else if( !strcmp(argv[i], "--audio") || !strcmp(argv[i], "-a") ) enable_audio = TRUE; else if( !strcmp(argv[i], "--silent") || !strcmp(argv[i], "-s") ) enable_audio = FALSE; else if( !strcmp(argv[i], "--halt") || !strcmp(argv[i], "-t") ) vm_halt = TRUE; else if( !strcmp(argv[i], "--loop") || !strcmp(argv[i], "-l") ) { vm_halt = FALSE; enable_server = TRUE; } else if( !strcmp(argv[i], "--server") ) enable_server = TRUE; else if( !strcmp(argv[i], "--standalone") ) enable_server = FALSE; else if( !strcmp(argv[i], "--callback") ) block = FALSE; else if( !strcmp(argv[i], "--blocking") ) block = TRUE; else if( !strcmp(argv[i], "--hid") ) load_hid = TRUE; else if( !strcmp(argv[i], "--shell") || !strcmp( argv[i], "-e" ) ) { enable_shell = TRUE; vm_halt = FALSE; } else if( !strcmp(argv[i], "--empty") ) no_vm = TRUE; else if( !strncmp(argv[i], "--srate", 7) ) srate = atoi( argv[i]+7 ) > 0 ? atoi( argv[i]+7 ) : srate; else if( !strncmp(argv[i], "-r", 2) ) srate = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : srate; else if( !strncmp(argv[i], "--bufsize", 9) ) buffer_size = atoi( argv[i]+9 ) > 0 ? atoi( argv[i]+9 ) : buffer_size; else if( !strncmp(argv[i], "-b", 2) ) buffer_size = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : buffer_size; else if( !strncmp(argv[i], "--bufnum", 8) ) num_buffers = atoi( argv[i]+8 ) > 0 ? atoi( argv[i]+8 ) : num_buffers; else if( !strncmp(argv[i], "-n", 2) ) num_buffers = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : num_buffers; else if( !strncmp(argv[i], "--dac", 5) ) dac = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0; else if( !strncmp(argv[i], "--adc", 5) ) adc = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 0; else if( !strncmp(argv[i], "--channels", 10) ) dac_chans = adc_chans = atoi( argv[i]+10 ) > 0 ? atoi( argv[i]+10 ) : 2; else if( !strncmp(argv[i], "-c", 2) ) dac_chans = adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--out", 5) ) dac_chans = atoi( argv[i]+5 ) > 0 ? atoi( argv[i]+5 ) : 2; else if( !strncmp(argv[i], "-o", 2) ) dac_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--in", 4) ) adc_chans = atoi( argv[i]+4 ) > 0 ? atoi( argv[i]+4 ) : 2; else if( !strncmp(argv[i], "-i", 2) ) adc_chans = atoi( argv[i]+2 ) > 0 ? atoi( argv[i]+2 ) : 2; else if( !strncmp(argv[i], "--level", 7) ) { g_priority = atoi( argv[i]+7 ); set_priority = TRUE; } else if( !strncmp(argv[i], "--watchdog", 10) ) { g_watchdog_timeout = atof( argv[i]+10 ); if( g_watchdog_timeout <= 0 ) g_watchdog_timeout = 0.5; do_watchdog = TRUE; } else if( !strncmp(argv[i], "--nowatchdog", 12) ) do_watchdog = FALSE; else if( !strncmp(argv[i], "--remote", 8) ) strcpy( g_host, argv[i]+8 ); else if( !strncmp(argv[i], "@", 1) ) strcpy( g_host, argv[i]+1 ); else if( !strncmp(argv[i], "--port", 6) ) g_port = atoi( argv[i]+6 ); else if( !strncmp(argv[i], "-p", 2) ) g_port = atoi( argv[i]+2 ); else if( !strncmp(argv[i], "--auto", 6) ) auto_depend = TRUE; else if( !strncmp(argv[i], "-u", 2) ) auto_depend = TRUE; else if( !strncmp(argv[i], "--log", 5) ) log_level = argv[i][5] ? atoi( argv[i]+5 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "--verbose", 9) ) log_level = argv[i][9] ? atoi( argv[i]+9 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "-v", 2) ) log_level = argv[i][2] ? atoi( argv[i]+2 ) : CK_LOG_INFO; else if( !strncmp(argv[i], "--deprecate", 11) ) { // get the rest string arg = argv[i]+11; if( arg == ":stop" ) deprecate_level = 0; else if( arg == ":warn" ) deprecate_level = 1; else if( arg == ":ignore" ) deprecate_level = 2; else { // error fprintf( stderr, "[chuck]: invalid arguments for '--deprecate'...\n" ); fprintf( stderr, "[chuck]: ... (looking for :stop, :warn, or :ignore)\n" ); exit( 1 ); } } else if( !strcmp( argv[i], "--probe" ) ) probe = TRUE; else if( !strcmp( argv[i], "--poop" ) ) uh(); else if( !strcmp(argv[i], "--help") || !strcmp(argv[i], "-h") || !strcmp(argv[i], "--about") ) { usage(); exit( 2 ); } else if( !strcmp( argv[i], "--version" ) ) { version(); exit( 2 ); } else { // boost log level g_otf_log = CK_LOG_CORE; // flag int is_otf = FALSE; // log level EM_setlog( log_level ); // do it if( otf_send_cmd( argc, argv, i, g_host, g_port, &is_otf ) ) exit( 0 ); // is otf if( is_otf ) exit( 1 ); // done fprintf( stderr, "[chuck]: invalid flag '%s'\n", argv[i] ); usage(); exit( 1 ); } } else files++; } // log level EM_setlog( log_level ); // probe if( probe ) { Digitalio::probe(); EM_error2b( 0, "" ); probeMidiIn(); EM_error2b( 0, "" ); probeMidiOut(); EM_error2b( 0, "" ); // exit exit( 0 ); } // check buffer size buffer_size = next_power_2( buffer_size-1 ); // check mode and blocking if( !enable_audio && !block ) block = TRUE; // audio, boost if( !set_priority && !block ) g_priority = g_priority_low; if( !set_priority && !enable_audio ) g_priority = 0x7fffffff; // set priority Chuck_VM::our_priority = g_priority; // set watchdog g_do_watchdog = do_watchdog; if ( !files && vm_halt && !enable_shell ) { fprintf( stderr, "[chuck]: no input files... (try --help)\n" ); exit( 1 ); } // shell initialization without vm if( enable_shell && no_vm ) { // instantiate g_shell = new Chuck_Shell; // initialize if( !init_shell( g_shell, new Chuck_Console, NULL ) ) exit( 1 ); // no vm is needed, just start running the shell now g_shell->run(); // clean up SAFE_DELETE( g_shell ); // done exit( 0 ); } // make sure vm if( no_vm ) { fprintf( stderr, "[chuck]: '--empty' can only be used with shell...\n" ); exit( 1 ); } // allocate the vm - needs the type system vm = g_vm = new Chuck_VM; if( !vm->initialize( enable_audio, vm_halt, srate, buffer_size, num_buffers, dac, adc, dac_chans, adc_chans, block ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } // allocate the compiler compiler = g_compiler = new Chuck_Compiler; // initialize the compiler if( !compiler->initialize( vm ) ) { fprintf( stderr, "[chuck]: error initializing compiler...\n" ); exit( 1 ); } // enable dump compiler->emitter->dump = dump; // set auto depend compiler->set_auto_depend( auto_depend ); // vm synthesis subsystem - needs the type system if( !vm->initialize_synthesis( ) ) { fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } // pre-load hid if( load_hid ) HidInManager::init(); // catch SIGINT signal( SIGINT, signal_int ); #ifndef __PLATFORM_WIN32__ // catch SIGPIPE signal( SIGPIPE, signal_pipe ); #endif // shell initialization if( enable_shell ) { // instantiate g_shell = new Chuck_Shell; // initialize if( !init_shell( g_shell, new Chuck_Console, vm ) ) exit( 1 ); } // set deprecate compiler->env->deprecate_level = deprecate_level; // reset count count = 1; // log EM_log( CK_LOG_SEVERE, "starting compilation..." ); // push indent EM_pushlog(); // loop through and process each file for( i = 1; i < argc; i++ ) { // make sure if( argv[i][0] == '-' || argv[i][0] == '+' ) { if( !strcmp(argv[i], "--dump") || !strcmp(argv[i], "+d" ) ) compiler->emitter->dump = TRUE; else if( !strcmp(argv[i], "--nodump") || !strcmp(argv[i], "-d" ) ) compiler->emitter->dump = FALSE; else get_count( argv[i], &count ); continue; } // parse out command line arguments if( !extract_args( argv[i], filename, args ) ) { // error fprintf( stderr, "[chuck]: malformed filename with argument list...\n" ); fprintf( stderr, " --> '%s'", argv[i] ); return 1; } // log EM_log( CK_LOG_FINE, "compiling '%s'...", filename.c_str() ); // push indent EM_pushlog(); // parse, type-check, and emit if( !compiler->go( filename, NULL ) ) return 1; // get the code code = compiler->output(); // name it code->name += string(argv[i]); // log EM_log( CK_LOG_FINE, "sporking %d %s...", count, count == 1 ? "instance" : "instances" ); // spork it while( count-- ) { // spork shred = vm->spork( code, NULL ); // add args shred->args = args; } // pop indent EM_poplog(); // reset count count = 1; } // pop indent EM_poplog(); // reset the parser reset_parse(); // boost priority if( Chuck_VM::our_priority != 0x7fffffff ) { // try if( !Chuck_VM::set_priority( Chuck_VM::our_priority, vm ) ) { // error fprintf( stderr, "[chuck]: %s\n", vm->last_error() ); exit( 1 ); } } // server if( enable_server ) { // log EM_log( CK_LOG_SYSTEM, "starting listener on port: %d...", g_port ); // start tcp server g_sock = ck_tcp_create( 1 ); if( !g_sock || !ck_bind( g_sock, g_port ) || !ck_listen( g_sock, 10 ) ) { fprintf( stderr, "[chuck]: cannot bind to tcp port %i...\n", g_port ); ck_close( g_sock ); g_sock = NULL; } else { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) pthread_create( &g_tid_otf, NULL, otf_cb, NULL ); #else g_tid_otf = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)otf_cb, NULL, 0, 0 ); #endif } } else { // log EM_log( CK_LOG_SYSTEM, "OTF server/listener: OFF" ); } // start shell on separate thread if( enable_shell ) { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) pthread_create( &g_tid_shell, NULL, shell_cb, g_shell ); #else g_tid_shell = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)shell_cb, g_shell, 0, 0 ); #endif } // run the vm vm->run(); // detach all_detach(); // free vm g_vm = NULL; SAFE_DELETE( vm ); // free the compiler SAFE_DELETE( compiler ); // wait for the shell, if it is running // does the VM reset its priority to normal before exiting? if( enable_shell ) while( g_shell != NULL ) usleep(10000); return 0; } chuck-1.2.0.8.dfsg/src/chuck_oo.cpp0000644000175000017500000006027610601706110015435 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_oo.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Autumn 2004 //----------------------------------------------------------------------------- #include "chuck_oo.h" #include "chuck_type.h" #include "chuck_vm.h" #include "chuck_instr.h" #include "chuck_errmsg.h" #include using namespace std; //----------------------------------------------------------------------------- // name: init_ref() // desc: initialize vm object //----------------------------------------------------------------------------- void Chuck_VM_Object::init_ref() { // set reference count m_ref_count = 0; // set flag m_pooled = FALSE; // set to not locked m_locked = FALSE; // set v ref m_v_ref = NULL; // add to vm allocator // Chuck_VM_Alloc::instance()->add_object( this ); } //----------------------------------------------------------------------------- // name: add_ref() // desc: add reference //----------------------------------------------------------------------------- void Chuck_VM_Object::add_ref() { // increment reference count m_ref_count++; // if going from 0 to 1 if( m_ref_count == 1 ) { // add to vm allocator Chuck_VM_Alloc::instance()->add_object( this ); } } //----------------------------------------------------------------------------- // name: release() // desc: remove reference //----------------------------------------------------------------------------- void Chuck_VM_Object::release() { // make sure there is at least one reference assert( m_ref_count > 0 ); // decrement m_ref_count--; // if no more references if( m_ref_count == 0 ) { // this is not good if( m_locked ) { EM_error2( 0, "internal error: releasing locked VM object!" ); // fail assert( FALSE ); // in case assert is disabled *(int *)0 = 1; } // tell the object manager to set this free Chuck_VM_Alloc::instance()->free_object( this ); } } //----------------------------------------------------------------------------- // name: lock() // desc: lock to keep from deleted //----------------------------------------------------------------------------- void Chuck_VM_Object::lock() { m_locked = TRUE; } // static member Chuck_VM_Alloc * Chuck_VM_Alloc::our_instance = NULL; //----------------------------------------------------------------------------- // name: instance() // desc: return static instance //----------------------------------------------------------------------------- Chuck_VM_Alloc * Chuck_VM_Alloc::instance() { if( !our_instance ) { our_instance = new Chuck_VM_Alloc; assert( our_instance != NULL ); } return our_instance; } //----------------------------------------------------------------------------- // name: add_object() // desc: add newly allocated vm object //----------------------------------------------------------------------------- void Chuck_VM_Alloc::add_object( Chuck_VM_Object * obj ) { // do log if( DO_LOG( CK_LOG_CRAZY ) ) { // log it EM_log( CK_LOG_CRAZY, "adding '%s' (0x%lx)...", mini_type( typeid(*obj).name() ), obj ); } // add it to map } //----------------------------------------------------------------------------- // name: free_object() // desc: free vm object - reference count should be 0 //----------------------------------------------------------------------------- void Chuck_VM_Alloc::free_object( Chuck_VM_Object * obj ) { // make sure the ref count is 0 assert( obj && obj->m_ref_count == 0 ); // do log if( DO_LOG( CK_LOG_FINEST ) ) { // log it EM_log( CK_LOG_FINEST, "freeing '%s' (0x%lx)...", mini_type( typeid(*obj).name() ), obj ); } // remove it from map // delete it delete obj; } //----------------------------------------------------------------------------- // name: Chuck_VM_Alloc() // desc: constructor //----------------------------------------------------------------------------- Chuck_VM_Alloc::Chuck_VM_Alloc() { } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Alloc() // desc: destructor //----------------------------------------------------------------------------- Chuck_VM_Alloc::~Chuck_VM_Alloc() { } //----------------------------------------------------------------------------- // name: Chuck_Object() // desc: constructor //----------------------------------------------------------------------------- Chuck_Object::Chuck_Object() { // zero virtual table vtable = NULL; // zero type type_ref = NULL; // zero size size = 0; // zero data data = NULL; // add to vm allocator Chuck_VM_Alloc::instance()->add_object( this ); } //----------------------------------------------------------------------------- // name: Chuck_Object() // desc: ... //----------------------------------------------------------------------------- Chuck_Object::~Chuck_Object() { // free if( vtable ) { delete vtable; vtable = NULL; } if( type_ref ) { type_ref->release(); type_ref = NULL; } if( data ) { delete [] data; size = 0; data = NULL; } } //----------------------------------------------------------------------------- // name: Chuck_Array4() // desc: constructor //----------------------------------------------------------------------------- Chuck_Array4::Chuck_Array4( t_CKBOOL is_obj, t_CKINT capacity ) { // sanity check assert( capacity >= 0 ); // reset size m_size = 0; // set capacity m_capacity = capacity; // set capacity m_vector.reserve( capacity ); // clear (as non-object, so no releases) m_is_obj = FALSE; this->clear(); // is object (set after clear) m_is_obj = is_obj; } //----------------------------------------------------------------------------- // name: ~Chuck_Array4() // desc: destructor //----------------------------------------------------------------------------- Chuck_Array4::~Chuck_Array4() { // do nothing } //----------------------------------------------------------------------------- // name: addr() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_Array4::addr( t_CKINT i ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; // get the addr return (t_CKUINT)(&m_vector[i]); } //----------------------------------------------------------------------------- // name: addr() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_Array4::addr( const string & key ) { // get the addr return (t_CKUINT)(&m_map[key]); } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::get( t_CKINT i, t_CKUINT * val ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; // get the value *val = m_vector[i]; // return good return 1; } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::get( const string & key, t_CKUINT * val ) { // set to zero *val = 0; // find map::iterator iter = m_map.find( key ); // check if( iter != m_map.end() ) *val = (*iter).second; // return good return 1; } //----------------------------------------------------------------------------- // name: set() // desc: include ref counting //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::set( t_CKINT i, t_CKUINT val ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; t_CKUINT v = m_vector[i]; // if obj if( m_is_obj && v ) ((Chuck_Object *)v)->release(); // set the value m_vector[i] = val; // if obj if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref(); // return good return 1; } //----------------------------------------------------------------------------- // name: set() // desc: include ref counting //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::set( const string & key, t_CKUINT val ) { map::iterator iter = m_map.find( key ); // if obj if( m_is_obj && iter != m_map.end() ) ((Chuck_Object *)(*iter).second)->release(); if( !val ) m_map.erase( key ); else m_map[key] = val; // if obj if( m_is_obj && val ) ((Chuck_Object *)val)->add_ref(); // return good return 1; } //----------------------------------------------------------------------------- // name: find() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::find( const string & key ) { return m_map.find( key ) != m_map.end(); } //----------------------------------------------------------------------------- // name: erase() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::erase( const string & key ) { map::iterator iter = m_map.find( key ); t_CKINT v = iter != m_map.end(); // if obj if( m_is_obj && iter != m_map.end() ) ((Chuck_Object *)(*iter).second)->release(); // erase if( v ) m_map.erase( key ); return v; } //----------------------------------------------------------------------------- // name: push_back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::push_back( t_CKUINT val ) { // check if( m_size + 1 < 0 ) return 0; // add to vector m_vector.push_back( val ); // reset capacity m_capacity = m_vector.capacity(); // track size m_size++; return 1; } //----------------------------------------------------------------------------- // name: pop_back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::pop_back( ) { // check if( m_size == 0 ) return 0; // if obj if( m_is_obj ) { Chuck_Object * v = (Chuck_Object *)m_vector[m_size-1]; if( v ) v->release(); } // zero m_vector[m_size-1] = 0; // add to vector m_vector.pop_back(); // track size m_size--; return 1; } //----------------------------------------------------------------------------- // name: back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::back( t_CKUINT * val ) const { // check if( m_size == 0 ) return 0; // get *val = m_vector.back(); return 1; } //----------------------------------------------------------------------------- // name: clear() // desc: ... //----------------------------------------------------------------------------- void Chuck_Array4::clear( ) { // clear vector m_vector.clear(); // zero zero( 0, m_capacity ); // set size m_size = 0; } //----------------------------------------------------------------------------- // name: set_capacity() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array4::set_capacity( t_CKINT capacity ) { // sanity check assert( capacity >= 0 ); // if clearing capacity if( capacity < m_capacity ) { // zero out section zero( capacity, m_capacity ); } // resize vector m_vector.reserve( capacity ); // set size m_size = m_size < capacity ? m_size : capacity; // set capacity m_capacity = capacity; return m_capacity; } //----------------------------------------------------------------------------- // name: zero() // desc: ... //----------------------------------------------------------------------------- void Chuck_Array4::zero( t_CKUINT start, t_CKUINT end ) { // sanity check assert( start <= m_capacity && end <= m_capacity ); // if contains objects if( m_is_obj ) { Chuck_Object * v = NULL; for( t_CKUINT i = start; i < end; i++ ) { // get it v = (Chuck_Object *)m_vector[i]; // release if( v ) { v->release(); m_vector[i] = 0; } } } else { for( t_CKUINT i = start; i < end; i++ ) { // zero m_vector[i] = 0; } } } //----------------------------------------------------------------------------- // name: Chuck_Array8() // desc: constructor //----------------------------------------------------------------------------- Chuck_Array8::Chuck_Array8( t_CKINT capacity ) { // sanity check assert( capacity >= 0 ); // reset size m_size = 0; // set capacity m_capacity = capacity; // set capacity m_vector.reserve( capacity ); // clear this->clear(); } //----------------------------------------------------------------------------- // name: ~Chuck_Array8() // desc: destructor //----------------------------------------------------------------------------- Chuck_Array8::~Chuck_Array8() { // do nothing } //----------------------------------------------------------------------------- // name: addr() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_Array8::addr( t_CKINT i ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; // get the addr return (t_CKUINT)(&m_vector[i]); } //----------------------------------------------------------------------------- // name: addr() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_Array8::addr( const string & key ) { // get the addr return (t_CKUINT)(&m_map[key]); } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::get( t_CKINT i, t_CKFLOAT * val ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; // get the value *val = m_vector[i]; // return good return 1; } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::get( const string & key, t_CKFLOAT * val ) { // set to zero *val = 0.0; // iterator map::iterator iter = m_map.find( key ); // check if( iter != m_map.end() ) { // get the value *val = (*iter).second; } // return good return 1; } //----------------------------------------------------------------------------- // name: set() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::set( t_CKINT i, t_CKFLOAT val ) { // bound check if( i < 0 || i >= (t_CKINT)m_capacity ) return 0; // set the value m_vector[i] = val; // return good return 1; } //----------------------------------------------------------------------------- // name: set() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::set( const string & key, t_CKFLOAT val ) { map::iterator iter = m_map.find( key ); if( !val ) m_map.erase( key ); else m_map[key] = val; // return good return 1; } //----------------------------------------------------------------------------- // name: set() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::find( const string & key ) { return m_map.find( key ) != m_map.end(); } //----------------------------------------------------------------------------- // name: set() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::erase( const string & key ) { return m_map.erase( key ); } //----------------------------------------------------------------------------- // name: push_back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::push_back( t_CKFLOAT val ) { // check if( m_size + 1 < 0 ) return 0; // add to vector m_vector.push_back( val ); // get capacity m_capacity = m_vector.capacity(); // track size m_size++; return 1; } //----------------------------------------------------------------------------- // name: pop_back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::pop_back( ) { // check if( m_size == 0 ) return 0; // zero m_vector[m_size-1] = 0.0; // add to vector m_vector.pop_back(); // track size m_size--; return 1; } //----------------------------------------------------------------------------- // name: back() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::back( t_CKFLOAT * val ) const { // check if( m_size == 0 ) return 0; // get *val = m_vector.back(); return 1; } //----------------------------------------------------------------------------- // name: clear() // desc: ... //----------------------------------------------------------------------------- void Chuck_Array8::clear( ) { // clear vector m_vector.clear(); // zero zero( 0, m_capacity ); // set size m_size = 0; } //----------------------------------------------------------------------------- // name: set_capacity() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Array8::set_capacity( t_CKINT capacity ) { // sanity check assert( capacity >= 0 ); // if less if( capacity < m_capacity ) zero( capacity, m_capacity ); // resize vector m_vector.reserve( capacity ); // set size m_size = m_size < capacity ? m_size : capacity; // set capacity m_capacity = capacity; return m_capacity; } //----------------------------------------------------------------------------- // name: zero() // desc: ... //----------------------------------------------------------------------------- void Chuck_Array8::zero( t_CKUINT start, t_CKUINT end ) { // sanity check assert( start <= m_capacity && end <= m_capacity ); for( t_CKUINT i = start; i < end; i++ ) { // zero m_vector[i] = 0.0; } } // static t_CKUINT Chuck_Event::our_can_wait = 0; //----------------------------------------------------------------------------- // name: signal() // desc: signal a event/condition variable, shreduling the next waiting shred // (if there is one or more) //----------------------------------------------------------------------------- void Chuck_Event::signal() { m_queue_lock.acquire(); if( !m_queue.empty() ) { Chuck_VM_Shred * shred = m_queue.front(); m_queue.pop(); m_queue_lock.release(); Chuck_VM_Shreduler * shreduler = shred->vm_ref->shreduler(); shred->event = NULL; shreduler->remove_blocked( shred ); shreduler->shredule( shred ); // push the current time t_CKTIME *& sp = (t_CKTIME *&)shred->reg->sp; push_( sp, shreduler->now_system ); } else m_queue_lock.release(); } //----------------------------------------------------------------------------- // name: remove() // desc: remove a shred from the event queue. //----------------------------------------------------------------------------- t_CKBOOL Chuck_Event::remove( Chuck_VM_Shred * shred ) { std::queue temp; t_CKBOOL removed = FALSE; m_queue_lock.acquire(); while( !m_queue.empty() ) { if( m_queue.front() != shred ) temp.push( m_queue.front() ); else { shred->event = NULL; removed = TRUE; } m_queue.pop(); } m_queue = temp; m_queue_lock.release(); return removed; } //----------------------------------------------------------------------------- // name: queue_broadcast() // desc: queue the event to broadcast a event/condition variable, by the owner // of the queue //----------------------------------------------------------------------------- void Chuck_Event::queue_broadcast() { // TODO: handle multiple VM m_queue_lock.acquire(); if( !m_queue.empty() ) { Chuck_VM_Shred * shred = m_queue.front(); m_queue_lock.release(); shred->vm_ref->queue_event( this, 1 ); } else m_queue_lock.release(); } //----------------------------------------------------------------------------- // name: broadcast() // desc: broadcast a event/condition variable, shreduling all waiting shreds //----------------------------------------------------------------------------- void Chuck_Event::broadcast() { m_queue_lock.acquire(); while( !m_queue.empty() ) { m_queue_lock.release(); this->signal(); m_queue_lock.acquire(); } m_queue_lock.release(); } //----------------------------------------------------------------------------- // name: wait() // desc: cause event/condition variable to block the current shred, putting it // on its waiting list, and suspennd the shred from the VM. //----------------------------------------------------------------------------- void Chuck_Event::wait( Chuck_VM_Shred * shred, Chuck_VM * vm ) { EM_log( CK_LOG_FINE, "shred '%d' wait on event '%x'...", shred->xid, (t_CKUINT)this ); // make sure the shred info matches the vm assert( shred->vm_ref == vm ); Chuck_DL_Return RETURN; f_mfun canwaitplease = (f_mfun)this->vtable->funcs[our_can_wait]->code->native_func; canwaitplease( this, NULL, &RETURN, shred ); // TODO: check this is right shred // RETURN.v_int = 1; // see if we can wait if( RETURN.v_int ) { // suspend shred->is_running = FALSE; // add to waiting list m_queue_lock.acquire(); m_queue.push( shred ); m_queue_lock.release(); // add event to shred assert( shred->event == NULL ); shred->event = this; // add shred to shreduler vm->shreduler()->add_blocked( shred ); } else // can't wait { // push the current time t_CKTIME *& sp = (t_CKTIME *&)shred->reg->sp; push_( sp, shred->now ); } } chuck-1.2.0.8.dfsg/src/chuck_oo.h0000644000175000017500000002023210600421721015067 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_oo.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_OO_H__ #define __CHUCK_OO_H__ #include "chuck_def.h" #include #include #include #include // forward reference struct Chuck_Type; struct Chuck_Value; struct Chuck_Func; struct Chuck_Namespace; struct Chuck_Context; struct Chuck_Env; struct Chuck_VM_Code; struct Chuck_VM_Shred; struct Chuck_VM; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Object // desc: base vm object //----------------------------------------------------------------------------- struct Chuck_VM_Object { public: Chuck_VM_Object() { this->init_ref(); } virtual ~Chuck_VM_Object() { } public: // add reference void add_ref(); // release reference void release(); // lock void lock(); public: t_CKUINT m_ref_count; // reference count t_CKBOOL m_pooled; // if true, this allocates from a pool t_CKBOOL m_locked; // if true, this should never be deleted public: // where std::vector * m_v_ref; private: void init_ref(); }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Alloc // desc: vm object manager //----------------------------------------------------------------------------- struct Chuck_VM_Alloc { public: static Chuck_VM_Alloc * instance(); public: void add_object( Chuck_VM_Object * obj ); void free_object( Chuck_VM_Object * obj ); protected: static Chuck_VM_Alloc * our_instance; protected: Chuck_VM_Alloc(); ~Chuck_VM_Alloc(); protected: // data std::map m_objects; }; //----------------------------------------------------------------------------- // name: struct Chuck_VTable // desc: virtual table //----------------------------------------------------------------------------- struct Chuck_VTable { public: std::vector funcs; }; //----------------------------------------------------------------------------- // name: struct Chuck_Object // dsec: base object //----------------------------------------------------------------------------- struct Chuck_Object : Chuck_VM_Object { public: Chuck_Object(); virtual ~Chuck_Object(); public: // virtual table Chuck_VTable * vtable; // reference to type Chuck_Type * type_ref; // the size of the data region t_CKUINT size; // data for the object t_CKBYTE * data; }; #define CHUCK_ARRAY4_DATASIZE 4 #define CHUCK_ARRAY8_DATASIZE 8 //----------------------------------------------------------------------------- // name: struct Chuck_Array // desc: native ChucK arrays ( virtual base class ) //----------------------------------------------------------------------------- struct Chuck_Array : Chuck_Object { // functionality that we can keep in common... public: // Chuck_Array(); // virtual ~Chuck_Array() { } virtual t_CKINT size( ) const { return m_size; } // array size virtual t_CKINT capacity( ) const { return m_capacity; } // array capacity virtual t_CKINT set_capacity( t_CKINT capacity ) = 0; // set virtual t_CKINT data_type_size( ) = 0; // size of stored type ( from type_ref ) virtual t_CKINT find( const std::string & key ) = 0; // find virtual t_CKINT erase( const std::string & key ) = 0; // erase virtual void clear( ) = 0; // clear public: t_CKUINT m_size; t_CKUINT m_capacity; }; //----------------------------------------------------------------------------- // name: struct Chuck_Array4 // desc: native ChucK arrays (for 4-byte) //----------------------------------------------------------------------------- struct Chuck_Array4 : Chuck_Array { public: Chuck_Array4( t_CKBOOL is_obj, t_CKINT capacity = 8 ); virtual ~Chuck_Array4(); public: t_CKUINT addr( t_CKINT i ); t_CKUINT addr( const std::string & key ); t_CKINT get( t_CKINT i, t_CKUINT * val ); t_CKINT get( const std::string & key, t_CKUINT * val ); t_CKINT set( t_CKINT i, t_CKUINT val ); t_CKINT set( const std::string & key, t_CKUINT val ); t_CKINT push_back( t_CKUINT val ); t_CKINT pop_back( ); t_CKINT back( t_CKUINT * val ) const; void zero( t_CKUINT start, t_CKUINT end ); virtual void clear( ); virtual t_CKINT set_capacity( t_CKINT capacity ); virtual t_CKINT find( const std::string & key ); virtual t_CKINT erase( const std::string & key ); virtual t_CKINT data_type_size( ) { return CHUCK_ARRAY4_DATASIZE; } public: std::vector m_vector; std::map m_map; t_CKBOOL m_is_obj; // t_CKINT m_size; // t_CKINT m_capacity; }; //----------------------------------------------------------------------------- // name: struct Chuck_Array8 // desc: native ChucK arrays (for 8-byte) //----------------------------------------------------------------------------- struct Chuck_Array8 : Chuck_Array { public: Chuck_Array8( t_CKINT capacity = 8 ); virtual ~Chuck_Array8(); public: t_CKUINT addr( t_CKINT i ); t_CKUINT addr( const std::string & key ); t_CKINT get( t_CKINT i, t_CKFLOAT * val ); t_CKINT get( const std::string & key, t_CKFLOAT * val ); t_CKINT set( t_CKINT i, t_CKFLOAT val ); t_CKINT set( const std::string & key, t_CKFLOAT val ); t_CKINT push_back( t_CKFLOAT val ); t_CKINT pop_back( ); t_CKINT back( t_CKFLOAT * val ) const; void zero( t_CKUINT start, t_CKUINT end ); virtual void clear( ); virtual t_CKINT set_capacity( t_CKINT capacity ); virtual t_CKINT find( const std::string & key ); virtual t_CKINT erase( const std::string & key ); virtual t_CKINT data_type_size( ) { return CHUCK_ARRAY8_DATASIZE; } public: std::vector m_vector; std::map m_map; // t_CKINT m_size; // t_CKINT m_capacity; }; #include "util_thread.h" //----------------------------------------------------------------------------- // name: Chuck_Event // desc: base Chuck Event class //----------------------------------------------------------------------------- struct Chuck_Event : Chuck_Object { public: void signal(); void broadcast(); void wait( Chuck_VM_Shred * shred, Chuck_VM * vm ); t_CKBOOL remove( Chuck_VM_Shred * shred ); public: // internal void queue_broadcast(); static t_CKUINT our_can_wait; std::queue m_queue; XMutex m_queue_lock; }; //----------------------------------------------------------------------------- // name: Chuck_String // desc: base Chuck string class //----------------------------------------------------------------------------- struct Chuck_String : Chuck_Object { public: Chuck_String( const std::string & s = "" ) { str = s; } ~Chuck_String() { } public: std::string str; }; #endif chuck-1.2.0.8.dfsg/src/chuck_otf.cpp0000644000175000017500000004612410600421721015605 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_otf.cpp // desc: on-the-fly programming utilities // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2004 //----------------------------------------------------------------------------- #include "chuck_otf.h" #include "chuck_compile.h" #include "chuck_errmsg.h" #include "chuck_globals.h" #include "util_thread.h" #include "util_string.h" #include #include #include #include #include #ifndef __PLATFORM_WIN32__ #include #endif using namespace std; // extern "C" void signal_int( int ); // log level t_CKUINT g_otf_log = CK_LOG_INFO; //----------------------------------------------------------------------------- // name: otf_hton( ) // desc: ... //----------------------------------------------------------------------------- void otf_hton( Net_Msg * msg ) { msg->header = htonl( msg->header ); msg->type = htonl( msg->type ); msg->param = htonl( msg->param ); msg->param2 = htonl( msg->param2 ); msg->param3 = htonl( msg->param3 ); msg->length = htonl( msg->length ); } //----------------------------------------------------------------------------- // name: otf_ntoh( ) // desc: ... //----------------------------------------------------------------------------- void otf_ntoh( Net_Msg * msg ) { msg->header = ntohl( msg->header ); msg->type = ntohl( msg->type ); msg->param = ntohl( msg->param ); msg->param2 = ntohl( msg->param2 ); msg->param3 = ntohl( msg->param3 ); msg->length = ntohl( msg->length ); } //----------------------------------------------------------------------------- // name: recv_file() // desc: ... //----------------------------------------------------------------------------- FILE * recv_file( const Net_Msg & msg, ck_socket sock ) { Net_Msg buf; // what is left // t_CKUINT left = msg.param2; // make a temp file FILE * fd = tmpfile(); do { // msg if( !ck_recv( sock, (char *)&buf, sizeof(buf) ) ) goto error; otf_ntoh( &buf ); // write fwrite( buf.buffer, sizeof(char), buf.length, fd ); }while( buf.param2 > 0 ); // check for error if( buf.param2 == NET_ERROR ) { // this was a problem EM_log( CK_LOG_INFO, "(via otf): received error flag, dropping..." ); // done goto error; } return fd; error: fclose( fd ); fd = NULL; return NULL; } //----------------------------------------------------------------------------- // name: otf_process_msg() // desc: ... //----------------------------------------------------------------------------- t_CKUINT otf_process_msg( Chuck_VM * vm, Chuck_Compiler * compiler, Net_Msg * msg, t_CKBOOL immediate, void * data ) { Chuck_Msg * cmd = new Chuck_Msg; Chuck_VM_Code * code = NULL; FILE * fd = NULL; t_CKUINT ret = 0; // fprintf( stderr, "UDP message recv...\n" ); if( msg->type == MSG_REPLACE || msg->type == MSG_ADD ) { string filename; vector args; // parse out command line arguments if( !extract_args( msg->buffer, filename, args ) ) { // error fprintf( stderr, "[chuck]: malformed filename with argument list...\n" ); fprintf( stderr, " --> '%s'", msg->buffer ); SAFE_DELETE(cmd); goto cleanup; } // copy stuff if( args.size() > 0 ) { strcpy( msg->buffer, filename.c_str() ); cmd->args = new vector; *(cmd->args) = args; } // see if entire file is on the way if( msg->param2 && msg->param2 != NET_ERROR ) { fd = recv_file( *msg, (ck_socket)data ); if( !fd ) { fprintf( stderr, "[chuck]: incoming source transfer '%s' failed...\n", mini(msg->buffer) ); SAFE_DELETE(cmd); goto cleanup; } } // parse, type-check, and emit if( !compiler->go( msg->buffer, fd ) ) { SAFE_DELETE(cmd); goto cleanup; } // get the code code = compiler->output(); // name it code->name += string(msg->buffer); // set the flags for the command cmd->type = msg->type; cmd->code = code; if( msg->type == MSG_REPLACE ) cmd->param = msg->param; } else if( msg->type == MSG_STATUS || msg->type == MSG_REMOVE || msg->type == MSG_REMOVEALL || msg->type == MSG_KILL || msg->type == MSG_TIME || msg->type == MSG_RESET_ID ) { cmd->type = msg->type; cmd->param = msg->param; } else { fprintf( stderr, "[chuck]: unrecognized incoming command from network: '%i'\n", cmd->type ); SAFE_DELETE(cmd); goto cleanup; } // immediate if( immediate ) ret = vm->process_msg( cmd ); else { vm->queue_msg( cmd, 1 ); ret = 1; } cleanup: // close file handle if( fd ) fclose( fd ); return ret; } //----------------------------------------------------------------------------- // name: otf_send_file() // desc: ... //----------------------------------------------------------------------------- int otf_send_file( const char * fname, Net_Msg & msg, const char * op, ck_socket dest ) { FILE * fd = NULL; struct stat fs; string filename; vector args; char buf[1024]; // parse out command line arguments if( !extract_args( fname, filename, args ) ) { // error fprintf( stderr, "[chuck]: malformed filename + argument list...\n" ); fprintf( stderr, " --> '%s'", fname ); return FALSE; } // filename and any args strcpy( msg.buffer, fname ); // test it strcpy( buf, filename.c_str() ); fd = open_cat_ck( buf ); if( !fd ) { fprintf( stderr, "[chuck]: cannot open file '%s' for [%s]...\n", filename.c_str(), op ); return FALSE; } if( !chuck_parse( (char *)filename.c_str(), fd ) ) { fprintf( stderr, "[chuck]: skipping file '%s' for [%s]...\n", filename.c_str(), op ); fclose( fd ); return FALSE; } // stat it memset( &fs, 0, sizeof(fs) ); stat( buf, &fs ); fseek( fd, 0, SEEK_SET ); // log EM_log( CK_LOG_INFO, "sending TCP file %s, size=%d", filename.c_str(), (t_CKUINT)fs.st_size ); EM_pushlog(); // send the first packet msg.param2 = (t_CKUINT)fs.st_size; msg.length = 0; otf_hton( &msg ); // go ck_send( dest, (char *)&msg, sizeof(msg) ); // send the whole thing t_CKUINT left = (t_CKUINT)fs.st_size; while( left ) { // log EM_log( CK_LOG_FINER, "%03d bytes left ... ", left ); // amount to send msg.length = left > NET_BUFFER_SIZE ? NET_BUFFER_SIZE : left; // read msg.param3 = fread( msg.buffer, sizeof(char), msg.length, fd ); // check for error if( !msg.param3 ) { // error encountered fprintf( stderr, "[chuck]: error while reading '%s'...\n", filename.c_str() ); // mark done left = 0; // error flag msg.param2 = NET_ERROR; } else { // amount left left -= msg.param3; // what's left msg.param2 = left; } // log EM_log( CK_LOG_FINER, "sending buffer %03d length %03d...", msg.param3, msg.length ); // send it otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } // pop log EM_poplog(); // close fclose( fd ); return TRUE; } //----------------------------------------------------------------------------- // name: otf_send_connect() // desc: ... //----------------------------------------------------------------------------- ck_socket otf_send_connect( const char * host, int port ) { // log EM_log( CK_LOG_INFO, "otf connect: %s:%i", host, port ); ck_socket sock = ck_tcp_create( 0 ); if( !sock ) { fprintf( stderr, "[chuck]: cannot open socket to send command...\n" ); return NULL; } if( strcmp( host, "127.0.0.1" ) ) EM_log( g_otf_log, "connecting to %s on port %i via TCP...", host, port ); if( !ck_connect( sock, host, port ) ) { fprintf( stderr, "cannot open TCP socket on %s:%i...\n", host, port ); ck_close( sock ); return NULL; } ck_send_timeout( sock, 0, 2000000 ); return sock; } //----------------------------------------------------------------------------- // name: otf_send_cmd() // desc: ... //----------------------------------------------------------------------------- int otf_send_cmd( int argc, char ** argv, t_CKINT & i, const char * host, int port, int * is_otf ) { Net_Msg msg; g_sigpipe_mode = 1; int tasks_total = 0, tasks_done = 0; ck_socket dest = NULL; if( is_otf ) *is_otf = TRUE; // log EM_log( CK_LOG_INFO, "examining otf command '%s'...", argv[i] ); if( !strcmp( argv[i], "--add" ) || !strcmp( argv[i], "+" ) ) { if( ++i >= argc ) { fprintf( stderr, "[chuck]: not enough arguments following [add]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "sending file:args '%s' for add...", mini(argv[i]) ); msg.type = MSG_ADD; msg.param = 1; tasks_done += otf_send_file( argv[i], msg, "add", dest ); tasks_total++; } while( ++i < argc ); // log EM_poplog(); if( !tasks_done ) goto error; } else if( !strcmp( argv[i], "--remove" ) || !strcmp( argv[i], "-" ) ) { if( ++i >= argc ) { fprintf( stderr, "[chuck]: not enough arguments following [remove]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); do { // log EM_log( CK_LOG_INFO, "requesting removal of shred '%i'..." ); msg.param = atoi( argv[i] ); msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); } while( ++i < argc ); // log EM_poplog(); } else if( !strcmp( argv[i], "--" ) ) { if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); // log EM_log( CK_LOG_INFO, "requesting removal of last shred..." ); msg.param = 0xffffffff; msg.type = MSG_REMOVE; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); // log EM_poplog(); } else if( !strcmp( argv[i], "--replace" ) || !strcmp( argv[i], "=" ) ) { if( ++i >= argc ) { fprintf( stderr, "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( i <= 0 ) msg.param = 0xffffffff; else msg.param = atoi( argv[i] ); if( ++i >= argc ) { fprintf( stderr, "[chuck]: not enough arguments following [replace]...\n" ); goto error; } if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); EM_log( CK_LOG_INFO, "requesting replace shred '%i' with '%s'...", msg.param, mini(argv[i]) ); msg.type = MSG_REPLACE; if( !otf_send_file( argv[i], msg, "replace", dest ) ) goto error; EM_poplog(); } else if( !strcmp( argv[i], "--removeall" ) || !strcmp( argv[i], "--remall" ) ) { if( !(dest = otf_send_connect( host, port )) ) return 0; EM_pushlog(); EM_log( CK_LOG_INFO, "requesting removeall..." ); msg.type = MSG_REMOVEALL; msg.param = 0; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); EM_poplog(); } else if( !strcmp( argv[i], "--kill" ) ) { if( !(dest = otf_send_connect( host, port )) ) return 0; msg.type = MSG_REMOVEALL; msg.param = 0; otf_hton( &msg ); ck_send( dest, (char *)&msg, sizeof(msg) ); msg.type = MSG_KILL; msg.param = (i+1) // defines #define NET_HEADER 0x8c8cc8c8 // buffer size #define NET_BUFFER_SIZE 512 // error value #define NET_ERROR 0xffffffff // forward struct Chuck_VM; struct Chuck_Compiler; //----------------------------------------------------------------------------- // name: struct Net_Msg() // desc: ... //----------------------------------------------------------------------------- struct Net_Msg { t_CKUINT header; t_CKUINT type; t_CKUINT param; t_CKUINT param2; t_CKUINT param3; t_CKUINT length; char buffer[NET_BUFFER_SIZE]; Net_Msg() { this->clear(); } void clear() { header = NET_HEADER; type = param = param2 = param3 = length = 0; memset( buffer, 0, sizeof(buffer) ); } }; // host to network void otf_hton( Net_Msg * msg ); // network to host void otf_ntoh( Net_Msg * msg ); // process incoming message t_CKUINT otf_process_msg( Chuck_VM * vm, Chuck_Compiler * compiler, Net_Msg * msg, t_CKBOOL immediate, void * data ); // send command int otf_send_cmd( int argc, char ** argv, t_CKINT & i, const char * host, int port, int * is_otf = NULL ); // send file to remote host int otf_send_file( const char * filename, Net_Msg & msg, const char * op, ck_socket sock ); // connect ck_socket otf_send_connect( const char * host, int port ); // callback void * otf_cb( void * p ); extern const char * poop[]; extern long poop_size; extern t_CKUINT g_otf_log; #endif chuck-1.2.0.8.dfsg/src/chuck_parse.cpp0000644000175000017500000001175510600421721016131 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_parse.cpp // desc: chuck parser interface // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #include "chuck_parse.h" #include "chuck_errmsg.h" #include using namespace std; // global static char g_filename[1024] = ""; // external extern "C" { extern FILE *yyin; } //----------------------------------------------------------------------------- // name: open_cat_ck() // desc: ... //----------------------------------------------------------------------------- FILE * open_cat_ck( c_str fname ) { FILE * fd = NULL; if( !(fd = fopen( fname, "rb" )) ) if( !strstr( fname, ".ck" ) && !strstr( fname, ".CK" ) ) { strcat( fname, ".ck" ); fd = fopen( fname, "rb" ); } return fd; } //----------------------------------------------------------------------------- // name: chuck_parse() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL chuck_parse( c_constr fname, FILE * fd, c_constr code ) { t_CKBOOL clo = FALSE; t_CKBOOL ret = FALSE; // sanity check if( fd && code ) { fprintf( stderr, "[chuck](via parser): (internal) both fd and code specified!\n" ); return FALSE; } // prepare code if( code ) { // ! assert( fd == NULL ); // generate temp file fd = tmpfile(); // flag it to close clo = TRUE; // write fwrite( code, sizeof(char), strlen(code), fd ); } /* // use code from memory buffer if its available if( code ) { // copy name strcpy( g_filename, fname ); // reset if( EM_reset( g_filename, NULL ) == FALSE ) goto cleanup; // TODO: clean g_program g_program = NULL; // clean yyrestart( NULL ); // load string (yy_scan_string will copy the C string) YY_BUFFER_STATE ybs = yy_scan_string( code ); if( !ybs ) goto cleanup; // parse if( !( yyparse() == 0 ) ) goto cleanup; // delete the lexer buffer yy_delete_buffer( ybs ); } */ // remember filename strcpy( g_filename, fname ); // test it if( !fd ) { fd = open_cat_ck( g_filename ); if( !fd ) strcpy( g_filename, fname ); else clo = TRUE; } // reset if( EM_reset( g_filename, fd ) == FALSE ) goto cleanup; // lexer/parser // TODO: if( yyin ) { fclose( yyin ); yyin = NULL; } // if no fd, open if( !fd ) { fd = fopen( g_filename, "r" ); if( fd ) clo = TRUE; } // if still none if( !fd ) { EM_error2( 0, "no such file or directory" ); goto cleanup; } // set to beginning else fseek( fd, 0, SEEK_SET ); // reset yyin to fd yyrestart( fd ); // check if( yyin == NULL ) goto cleanup; // TODO: clean g_program g_program = NULL; // parse if( !(yyparse( ) == 0) ) goto cleanup; // flag success ret = TRUE; cleanup: // done if( clo ) fclose( fd ); return ret; } //------------------------------------------------------------------------------ // name: reset_parse() // desc: ... //------------------------------------------------------------------------------ void reset_parse( ) { // empty file name EM_change_file( NULL ); } //----------------------------------------------------------------------------- // name: parseLine() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL SyntaxQuery::parseLine( const std::string & line, SyntaxTokenList & tokens ) { // clear the token list tokens.howmany = 0; return TRUE; } chuck-1.2.0.8.dfsg/src/chuck_parse.h0000644000175000017500000000732610600421721015575 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_parse.h // desc: chuck parser interface (using flex and bison) // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 - original in chuck_main.cpp // Autumn 2005 - this file //----------------------------------------------------------------------------- #ifndef __CHUCK_PARSE_H__ #define __CHUCK_PARSE_H__ #include "chuck_def.h" #include "chuck_absyn.h" #include #include // 'C' specification necessary for windows to link properly #ifdef __PLATFORM_WIN32__ extern "C" a_Program g_program; #else extern a_Program g_program; #endif // link with the parser extern "C" int yyparse( void ); extern "C" void yyrestart( FILE * ); struct yy_buffer_state; typedef yy_buffer_state * YY_BUFFER_STATE; extern "C" YY_BUFFER_STATE yy_scan_string( const char * ); extern "C" void yy_delete_buffer( YY_BUFFER_STATE ); // open file with .ck append as appropriate FILE * open_cat_ck( c_str filename ); // parse file t_CKBOOL chuck_parse( c_constr fname, FILE * fd = NULL, c_constr code = NULL ); // reset the parser void reset_parse( ); // syntax highlighting tools #include // syntax types (for highlighting) enum SyntaxType { COMMA = 0, SEMICOLON, DBLCOLON, PAREN, DOT, CHUCK_OP, OPERATOR, KEYWORD, DEBUG_PRINT, SPORK, INTEGER, FLOATING, STRING, COMMENT, OTHER, NUM_SYNTAX_TYPES }; // token info struct SyntaxToken { // the token std::string token; // type t_CKUINT type; // from the beginning of line std::string::size_type begin; // from the beginning of line std::string::size_type end; // constructor SyntaxToken() : type(0) { } // copy constructor SyntaxToken( const SyntaxToken & rhs ) { token = rhs.token; type = rhs.type; begin = rhs.begin; end = rhs.end; } }; // token list struct SyntaxTokenList { std::vector list; std::vector::size_type howmany; // copy constructor SyntaxTokenList( const SyntaxTokenList & rhs ) { // copy howmany = rhs.howmany; // allocate list.resize( howmany ); // copy for( std::vector::size_type i = 0; i < howmany; i++ ) list[i] = rhs.list[i]; } SyntaxTokenList() { howmany = 0; } }; // token query struct SyntaxQuery { public: t_CKBOOL parseLine( const std::string & line, SyntaxTokenList & tokens ); }; #endif chuck-1.2.0.8.dfsg/src/chuck_scan.cpp0000644000175000017500000023667110600421721015751 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_scan.cpp // desc: chuck type-system / type-checker pre-scan // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 - original //----------------------------------------------------------------------------- #include "chuck_type.h" #include "chuck_scan.h" #include "chuck_errmsg.h" #include "chuck_vm.h" #include "util_string.h" using namespace std; //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list ); t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ); t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt ); t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt ); t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt ); t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt ); t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt ); t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt ); t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp ); t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary ); t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast ); t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ); t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur ); t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array ); t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ); t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ); t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ); t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if ); t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list ); t_CKBOOL type_engine_scan1_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ); t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list ); t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt ); t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt ); t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt ); t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt ); t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt ); t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt ); t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt ); t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp ); t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary ); t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ); t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast ); t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ); t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur ); t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array ); t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ); t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ); t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ); t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if ); t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list ); t_CKBOOL type_engine_scan2_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ); t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ); t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ); //----------------------------------------------------------------------------- // name: type_engine_scan0_prog() // desc: data in env should be ready : type discovery //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 0) type discovery scan '%s'...", env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // do nothing break; case ae_section_func: // do nothing break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // make global, if marked public if( prog->section->class_def->decl == ae_key_public ) { // make sure the context has no public class if( env->context->public_class_def != NULL ) { EM_error2( prog->section->class_def->linepos, "more than one 'public' class defined..." ); ret = FALSE; continue; } // make global prog->section->class_def->home = env->global(); // remember env->context->public_class_def = prog->section->class_def; } // scan the class definition ret = type_engine_scan0_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan0_class_def() // desc: add defined class to env - this is the main goal of scan0 //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def class_def ) { // make new type for class def t_CKTYPE the_class = NULL; // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // log EM_log( CK_LOG_FINER, "scanning class definition '%s'...", S_name(class_def->name->xid) ); // push indent EM_pushlog(); // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import if( class_def->home != NULL ) { // log EM_log( CK_LOG_FINER, "target namespace: '%s'", class_def->home->name.c_str() ); // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = class_def->home; } // make sure class not already in namespace if( env->curr->lookup_type( class_def->name->xid, FALSE ) ) { EM_error2( class_def->name->linepos, "class/type '%s' is already defined in namespace '%s'", S_name(class_def->name->xid), env->curr->name.c_str() ); ret = FALSE; goto done; } // check if reserved if( type_engine_check_reserved( env, class_def->name->xid, class_def->name->linepos ) ) { EM_error2( class_def->name->linepos, "...in class definition '%s'", S_name(class_def->name->xid) ); ret = FALSE; goto done; } // allocate new type assert( env->context != NULL ); the_class = env->context->new_Chuck_Type(); // add reference SAFE_ADD_REF( the_class ); // set the fields the_class->xid = te_user; the_class->name = S_name(class_def->name->xid); the_class->owner = env->curr; the_class->array_depth = 0; the_class->size = sizeof(void *); the_class->obj_size = 0; // TODO: the_class->info = env->context->new_Chuck_Namespace(); SAFE_ADD_REF( the_class->info ); the_class->info->name = the_class->name; // if public class, then set parent to context // ... allowing the class to address current context if( env->context->public_class_def == class_def ) { the_class->info->parent = env->context->nspc; } else { the_class->info->parent = env->curr; } // TODO: add ref to the parent? the_class->func = NULL; the_class->def = class_def; // add code the_class->info->pre_ctor = new Chuck_VM_Code; SAFE_ADD_REF( the_class->info->pre_ctor ); // add to env env->curr->type.add( the_class->name, the_class ); // URGENT: make this global // incomplete the_class->is_complete = FALSE; // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: break; case ae_section_func: break; case ae_section_class: // do the class ret = type_engine_scan0_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); // if things checked out if( ret ) { Chuck_Value * value = NULL; Chuck_Type * type = NULL; // allocate value type = t_class.copy( env ); type->actual_type = the_class; value = env->context->new_Chuck_Value( type, the_class->name ); value->owner = env->curr; value->is_const = TRUE; value->is_member = FALSE; // add to env env->curr->value.add( the_class->name, value ); // remember class_def->type = the_class; } // if nspc is attached to class_def, that means the class_def is to be // put in that namespace. this is usually the case when doing import // we undo that extra namespace layer here... if( class_def->home != NULL ) { // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); } else // set the current namespace as home { // set curr as home class_def->home = env->curr; } done: // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_prog() // desc: data in env should be ready //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 1) type resolution scan '%s'...", env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the statements ret = type_engine_scan1_stmt_list( env, prog->section->stmt_list ); break; case ae_section_func: // if only classes, then skip if( how_much == te_do_classes_only ) break; // scan the function definition ret = type_engine_scan1_func_def( env, prog->section->func_def ); break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // scan the class definition ret = type_engine_scan1_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_stmt_list( Chuck_Env * env, a_Stmt_List list ) { // type check the stmt_list while( list ) { // the current statement if( !type_engine_scan1_stmt( env, list->stmt ) ) return FALSE; // advance to the next statement list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_stmt(() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_stmt( Chuck_Env * env, a_Stmt stmt ) { t_CKBOOL ret = FALSE; if( !stmt ) return TRUE; // the type of stmt switch( stmt->s_type ) { case ae_stmt_if: // count scope to help determine class member env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_if( env, &stmt->stmt_if ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_for: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_for( env, &stmt->stmt_for ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_while: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_while( env, &stmt->stmt_while ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_until: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_until( env, &stmt->stmt_until ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_loop: env->class_scope++; env->curr->value.push(); ret = type_engine_scan1_loop( env, &stmt->stmt_loop ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_exp: ret = type_engine_scan1_exp( env, stmt->stmt_exp ); break; case ae_stmt_return: ret = type_engine_scan1_return( env, &stmt->stmt_return ); break; case ae_stmt_code: env->class_scope++; ret = type_engine_scan1_code_segment( env, &stmt->stmt_code ); env->class_scope--; break; case ae_stmt_break: ret = type_engine_scan1_break( env, &stmt->stmt_break ); break; case ae_stmt_continue: ret = type_engine_scan1_continue( env, &stmt->stmt_continue ); break; case ae_stmt_switch: env->class_scope++; ret = type_engine_scan1_switch( env, &stmt->stmt_switch ); env->class_scope--; break; case ae_stmt_case: // ret = type_engine_scan1_case( env, &stmt->stmt_case ); break; case ae_stmt_gotolabel: // ret = type_engine_scan1_gotolabel( env, &stmt->goto_label ); break; default: EM_error2( stmt->linepos, "internal compiler error (pre-scan) - no stmt type '%i'!", stmt->s_type ); ret = FALSE; break; } return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_if( Chuck_Env * env, a_Stmt_If stmt ) { // check the conditional if( !type_engine_scan1_exp( env, stmt->cond ) ) return FALSE; // TODO: ensure that conditional has valid type // check if if( !type_engine_scan1_stmt( env, stmt->if_body ) ) return FALSE; // check else, if there is one if( stmt->else_body ) if( !type_engine_scan1_stmt( env, stmt->else_body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_for() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_for( Chuck_Env * env, a_Stmt_For stmt ) { // check the initial if( !type_engine_scan1_stmt( env, stmt->c1 ) ) return FALSE; // check the conditional if( !type_engine_scan1_stmt( env, stmt->c2 ) ) return FALSE; // TODO: same as if - check conditional type valid // check the post if( stmt->c3 && !type_engine_scan1_exp( env, stmt->c3 ) ) return FALSE; // check body if( !type_engine_scan1_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_while() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_while( Chuck_Env * env, a_Stmt_While stmt ) { // check the conditional if( !type_engine_scan1_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan1_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_until() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_until( Chuck_Env * env, a_Stmt_Until stmt ) { // check the conditional if( !type_engine_scan1_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan1_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_loop() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_loop( Chuck_Env * env, a_Stmt_Loop stmt ) { // check the conditional if( !type_engine_scan1_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan1_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_switch() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_switch( Chuck_Env * env, a_Stmt_Switch stmt ) { // TODO: implement this EM_error2( stmt->linepos, "switch not implemented..." ); return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_break() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_break( Chuck_Env * env, a_Stmt_Break br ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_continue() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_continue( Chuck_Env * env, a_Stmt_Continue cont ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_return() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_return( Chuck_Env * env, a_Stmt_Return stmt ) { t_CKBOOL ret = FALSE; // check the type of the return if( stmt->val ) ret = type_engine_scan1_exp( env, stmt->val ); else ret = TRUE; return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_code_segment() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push ) { // class env->class_scope++; // push if( push ) env->curr->value.push(); // env->context->nspc.value.push(); // do it t_CKBOOL t = type_engine_scan1_stmt_list( env, stmt->stmt_list ); // pop if( push ) env->curr->value.pop(); // env->context->nspc.value.pop(); // class env->class_scope--; return t; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp( Chuck_Env * env, a_Exp exp ) { a_Exp curr = exp; t_CKBOOL ret = TRUE; // loop through parallel expressions while( curr ) { // examine the syntax switch( curr->s_type ) { case ae_exp_binary: ret = type_engine_scan1_exp_binary( env, &curr->binary ); break; case ae_exp_unary: ret = type_engine_scan1_exp_unary( env, &curr->unary ); break; case ae_exp_cast: ret = type_engine_scan1_exp_cast( env, &curr->cast ); break; case ae_exp_postfix: ret = type_engine_scan1_exp_postfix( env, &curr->postfix ); break; case ae_exp_dur: ret = type_engine_scan1_exp_dur( env, &curr->dur ); break; case ae_exp_primary: ret = type_engine_scan1_exp_primary( env, &curr->primary ); break; case ae_exp_array: ret = type_engine_scan1_exp_array( env, &curr->array ); break; case ae_exp_func_call: ret = type_engine_scan1_exp_func_call( env, &curr->func_call ); break; case ae_exp_dot_member: ret = type_engine_scan1_exp_dot_member( env, &curr->dot_member ); break; case ae_exp_if: ret = type_engine_scan1_exp_if( env, &curr->exp_if ); break; case ae_exp_decl: ret = type_engine_scan1_exp_decl( env, &curr->decl ); break; default: EM_error2( curr->linepos, "internal compiler error - no expression type '%i'...", curr->s_type ); return FALSE; } // error if( !ret ) return FALSE; // advance to next expression curr = curr->next; } // return type return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_binary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_binary( Chuck_Env * env, a_Exp_Binary binary ) { a_Exp cl = binary->lhs, cr = binary->rhs; // type check the lhs and rhs t_CKBOOL left = type_engine_scan1_exp( env, cl ); t_CKBOOL right = type_engine_scan1_exp( env, cr); // if either fails, then return FALSE if( !left || !right ) return FALSE; // cross chuck while( cr ) { // type check the pair if( !type_engine_scan1_op( env, binary->op, cl, cr, binary ) ) return FALSE; cr = cr->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_op() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { // TODO: check for static here return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_op_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_op_unchuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_op_at_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_unary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_unary( Chuck_Env * env, a_Exp_Unary unary ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_primary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_primary( Chuck_Env * env, a_Exp_Primary exp ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_array_lit() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ) { // verify there are no errors from the parser... if( !verify_array( exp->array ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_cast() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_cast( Chuck_Env * env, a_Exp_Cast cast ) { // check the exp t_CKBOOL t = type_engine_scan1_exp( env, cast->exp ); if( !t ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_dur() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_dur( Chuck_Env * env, a_Exp_Dur dur ) { // type check the two components t_CKBOOL base = type_engine_scan1_exp( env, dur->base ); t_CKBOOL unit = type_engine_scan1_exp( env, dur->unit ); // make sure both type check if( !base || !unit ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_postfix() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ) { // check the exp t_CKBOOL t = type_engine_scan1_exp( env, postfix->exp ); if( !t ) return FALSE; // syntax // TODO: figure out ++/-- switch( postfix->op ) { case ae_op_plusplus: case ae_op_minusminus: // assignable? if( postfix->exp->s_meta != ae_meta_var ) { EM_error2( postfix->exp->linepos, "postfix operator '%s' cannot be used on non-mutable data-type...", op2str( postfix->op ) ); return FALSE; } // TODO: mark somewhere we need to post increment return TRUE; break; default: // no match EM_error2( postfix->linepos, "internal compiler error (pre-scan): unrecognized postfix '%i'", postfix->op ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_if( Chuck_Env * env, a_Exp_If exp_if ) { // check the components t_CKBOOL cond = type_engine_scan1_exp( env, exp_if->cond ); t_CKBOOL if_exp = type_engine_scan1_exp( env, exp_if->if_exp ); t_CKBOOL else_exp = type_engine_scan1_exp( env, exp_if->else_exp ); // make sure everything good if( !cond || !if_exp || !else_exp ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_array_subscripts( ) // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_array_subscripts( Chuck_Env * env, a_Exp exp_list ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_decl( ) // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl ) { a_Var_Decl_List list = decl->var_decl_list; a_Var_Decl var_decl = NULL; // look up the type // TODO: handle T a, b, c... // TODO: do we climb? t_CKTYPE t = type_engine_find_type( env, decl->type->xid ); // if not found, try to resolve if( !t ) { // resolve EM_error2( decl->linepos, "... in declaration ..." ); return FALSE; } // loop through the variables while( list != NULL ) { // get the decl var_decl = list->var_decl; // count decl->num_var_decls++; // scan if array if( var_decl->array != NULL ) { // verify there are no errors from the parser... if( !verify_array( var_decl->array ) ) return FALSE; // may be partial and empty [] if( var_decl->array->exp_list ) { // type check the exp if( !type_engine_scan1_exp( env, var_decl->array->exp_list ) ) return FALSE; // make sure types are of int if( !type_engine_scan1_array_subscripts( env, var_decl->array->exp_list ) ) return FALSE; } } // the next var decl list = list->next; } // remember : decl->ck_type = t; SAFE_REF_ASSIGN( decl->ck_type, t ); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ) { // Chuck_Func * func = NULL; // Chuck_Func * up = NULL; // type check the func t_CKBOOL f = type_engine_scan1_exp( env, exp_func ); if( !f ) return FALSE; // check the arguments if( args ) { t_CKBOOL a = type_engine_scan1_exp( env, args ); if( !a ) return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ) { // type check it return type_engine_scan1_exp_func_call( env, func_call->func, func_call->args, func_call->ck_func, func_call->linepos ); } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_dot_member() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ) { // type check the base t_CKBOOL base = type_engine_scan1_exp( env, member->base ); if( !base ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_exp_array() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_exp_array( Chuck_Env * env, a_Exp_Array array ) { // verify there are no errors from the parser... if( !verify_array( array->indices ) ) return FALSE; // type check the base t_CKBOOL base = type_engine_scan1_exp( env, array->base ); if( !base ) return FALSE; // type check the index t_CKBOOL index = type_engine_scan1_exp( env, array->indices->exp_list ); if( !index ) return FALSE; // cycle through each exp // a_Exp e = array->indices->exp_list; // count the dimension // t_CKUINT depth = 0; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan1_class_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def class_def ) { // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // the class Chuck_Type * the_class = class_def->type; // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: // do the statements ret = type_engine_scan1_stmt_list( env, body->section->stmt_list ); break; case ae_section_func: // do the function ret = type_engine_scan1_func_def( env, body->section->func_def ); break; case ae_section_class: // do the class ret = type_engine_scan1_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan1_func_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def f ) { a_Arg_List arg_list = NULL; t_CKUINT count = 0; // t_CKBOOL has_code = FALSE; // Chuck_Value * v = NULL; // if not imported, then check to make sure no reserved word conflict // if( f->s_type != ae_func_builtin ) // TODO: fix this // check if reserved if( type_engine_check_reserved( env, f->name, f->linepos ) ) { EM_error2( f->linepos, "...in function definition '%s'", S_name(f->name) ); return FALSE; } // look up the return type f->ret_type = type_engine_find_type( env, f->type_decl->xid ); // no return type if( !f->ret_type ) { // TODO: try to resolve EM_error2( f->linepos, "... in return type of function '%s' ...", S_name(f->name) ); goto error; } // check if array if( f->type_decl->array != NULL ) { // verify there are no errors from the parser... if( !verify_array( f->type_decl->array ) ) return FALSE; Chuck_Type * t = NULL; Chuck_Type * t2 = f->ret_type; // should be partial and empty [] if( f->type_decl->array->exp_list ) { EM_error2( f->type_decl->array->linepos, "function '%s':", S_name(f->name) ); EM_error2( f->type_decl->array->linepos, "return array type must be defined with empty []'s" ); return FALSE; } // create the new array type t = new_array_type( env, // the env &t_array, // the array base class, usually &t_array f->type_decl->array->depth, // the depth of the new type t2, // the 'array_type' env->curr // the owner namespace ); // TODO: verify // set ref f->type_decl->ref = TRUE; // replace type : f->ret_type = t SAFE_REF_ASSIGN( f->ret_type, t ); } // look up types for the function arguments arg_list = f->arg_list; // count count = 1; // loop over arguments while( arg_list ) { // look up in type table arg_list->type = type_engine_find_type( env, arg_list->type_decl->xid ); // if not there, try to resolve if( !arg_list->type ) { // TODO: try to resolve // EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) ); EM_error2( arg_list->linepos, "... in argument %i '%s' of function '%s(.)' ...", count, S_name(arg_list->var_decl->xid), S_name(f->name) ); goto error; } // count count++; // next arg arg_list = arg_list->next; } // scan the code for types that need resolution assert( f->code == NULL || f->code->s_type == ae_stmt_code ); if( f->code && !type_engine_scan1_code_segment( env, &f->code->stmt_code, FALSE ) ) { EM_error2( 0, "...in function '%s'", S_name(f->name) ); goto error; } return TRUE; error: return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_prog() // desc: data in env should be ready //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_prog( Chuck_Env * env, a_Program prog, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; if( !prog ) return FALSE; // log EM_log( CK_LOG_FINER, "(pass 2) type verification scan '%s'...", env->context->filename.c_str() ); // push indent EM_pushlog(); // log how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // if classes only, then skip if( how_much == te_do_classes_only ) break; // scan the statements ret = type_engine_scan2_stmt_list( env, prog->section->stmt_list ); break; case ae_section_func: // if classes only, then skip if( how_much == te_do_classes_only ) break; // scan the function definition ret = type_engine_scan2_func_def( env, prog->section->func_def ); break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // scan the class definition ret = type_engine_scan2_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker pre-scan..." ); ret = FALSE; break; } prog = prog->next; } // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan2_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_stmt_list( Chuck_Env * env, a_Stmt_List list ) { // type check the stmt_list while( list ) { // the current statement if( !type_engine_scan2_stmt( env, list->stmt ) ) return FALSE; // advance to the next statement list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_stmt(() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_stmt( Chuck_Env * env, a_Stmt stmt ) { t_CKBOOL ret = FALSE; if( !stmt ) return TRUE; // the type of stmt switch( stmt->s_type ) { case ae_stmt_if: // count scope to help determine class member env->class_scope++; env->curr->value.push(); ret = type_engine_scan2_if( env, &stmt->stmt_if ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_for: env->class_scope++; env->curr->value.push(); ret = type_engine_scan2_for( env, &stmt->stmt_for ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_while: env->class_scope++; env->curr->value.push(); ret = type_engine_scan2_while( env, &stmt->stmt_while ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_until: env->class_scope++; env->curr->value.push(); ret = type_engine_scan2_until( env, &stmt->stmt_until ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_loop: env->class_scope++; env->curr->value.push(); ret = type_engine_scan2_loop( env, &stmt->stmt_loop ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_exp: ret = type_engine_scan2_exp( env, stmt->stmt_exp ); break; case ae_stmt_return: ret = type_engine_scan2_return( env, &stmt->stmt_return ); break; case ae_stmt_code: env->class_scope++; ret = type_engine_scan2_code_segment( env, &stmt->stmt_code ); env->class_scope--; break; case ae_stmt_break: ret = type_engine_scan2_break( env, &stmt->stmt_break ); break; case ae_stmt_continue: ret = type_engine_scan2_continue( env, &stmt->stmt_continue ); break; case ae_stmt_switch: env->class_scope++; ret = type_engine_scan2_switch( env, &stmt->stmt_switch ); env->class_scope--; break; case ae_stmt_case: // ret = type_engine_scan2_case( env, &stmt->stmt_case ); break; case ae_stmt_gotolabel: // ret = type_engine_scan2_gotolabel( env, &stmt->goto_label ); break; default: EM_error2( stmt->linepos, "internal compiler error (pre-scan) - no stmt type '%i'!", stmt->s_type ); ret = FALSE; break; } return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan2_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_if( Chuck_Env * env, a_Stmt_If stmt ) { // check the conditional if( !type_engine_scan2_exp( env, stmt->cond ) ) return FALSE; // TODO: ensure that conditional has valid type // check if if( !type_engine_scan2_stmt( env, stmt->if_body ) ) return FALSE; // check else, if there is one if( stmt->else_body ) if( !type_engine_scan2_stmt( env, stmt->else_body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_for() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_for( Chuck_Env * env, a_Stmt_For stmt ) { // check the initial if( !type_engine_scan2_stmt( env, stmt->c1 ) ) return FALSE; // check the conditional if( !type_engine_scan2_stmt( env, stmt->c2 ) ) return FALSE; // TODO: same as if - check conditional type valid // check the post if( stmt->c3 && !type_engine_scan2_exp( env, stmt->c3 ) ) return FALSE; // check body if( !type_engine_scan2_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_while() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_while( Chuck_Env * env, a_Stmt_While stmt ) { // check the conditional if( !type_engine_scan2_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan2_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_until() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_until( Chuck_Env * env, a_Stmt_Until stmt ) { // check the conditional if( !type_engine_scan2_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan2_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_loop() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_loop( Chuck_Env * env, a_Stmt_Loop stmt ) { // check the conditional if( !type_engine_scan2_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // check the body if( !type_engine_scan2_stmt( env, stmt->body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_switch() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_switch( Chuck_Env * env, a_Stmt_Switch stmt ) { // TODO: implement this EM_error2( stmt->linepos, "switch not implemented..." ); return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_break() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_break( Chuck_Env * env, a_Stmt_Break br ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_continue() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_continue( Chuck_Env * env, a_Stmt_Continue cont ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_return() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_return( Chuck_Env * env, a_Stmt_Return stmt ) { t_CKBOOL ret = FALSE; // check the type of the return if( stmt->val ) ret = type_engine_scan2_exp( env, stmt->val ); else ret = TRUE; return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan2_code_segment() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push ) { // class env->class_scope++; // push if( push ) env->curr->value.push(); // env->context->nspc.value.push(); // do it t_CKBOOL t = type_engine_scan2_stmt_list( env, stmt->stmt_list ); // pop if( push ) env->curr->value.pop(); // env->context->nspc.value.pop(); // class env->class_scope--; return t; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp( Chuck_Env * env, a_Exp exp ) { a_Exp curr = exp; t_CKBOOL ret = TRUE; // loop through parallel expressions while( curr ) { // examine the syntax switch( curr->s_type ) { case ae_exp_binary: ret = type_engine_scan2_exp_binary( env, &curr->binary ); break; case ae_exp_unary: ret = type_engine_scan2_exp_unary( env, &curr->unary ); break; case ae_exp_cast: ret = type_engine_scan2_exp_cast( env, &curr->cast ); break; case ae_exp_postfix: ret = type_engine_scan2_exp_postfix( env, &curr->postfix ); break; case ae_exp_dur: ret = type_engine_scan2_exp_dur( env, &curr->dur ); break; case ae_exp_primary: ret = type_engine_scan2_exp_primary( env, &curr->primary ); break; case ae_exp_array: ret = type_engine_scan2_exp_array( env, &curr->array ); break; case ae_exp_func_call: ret = type_engine_scan2_exp_func_call( env, &curr->func_call ); break; case ae_exp_dot_member: ret = type_engine_scan2_exp_dot_member( env, &curr->dot_member ); break; case ae_exp_if: ret = type_engine_scan2_exp_if( env, &curr->exp_if ); break; case ae_exp_decl: ret = type_engine_scan2_exp_decl( env, &curr->decl ); break; default: EM_error2( curr->linepos, "internal compiler error - no expression type '%i'...", curr->s_type ); return FALSE; } // error if( !ret ) return FALSE; // advance to next expression curr = curr->next; } // return type return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_binary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_binary( Chuck_Env * env, a_Exp_Binary binary ) { a_Exp cl = binary->lhs, cr = binary->rhs; // type check the lhs and rhs t_CKBOOL left = type_engine_scan2_exp( env, cl ); t_CKBOOL right = type_engine_scan2_exp( env, cr); // if either fails, then return FALSE if( !left || !right ) return FALSE; // cross chuck while( cr ) { // type check the pair if( !type_engine_scan2_op( env, binary->op, cl, cr, binary ) ) return FALSE; cr = cr->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_op() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { // TODO: check for static here return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_op_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_op_unchuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_op_at_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_unary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_unary( Chuck_Env * env, a_Exp_Unary unary ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_primary() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_primary( Chuck_Env * env, a_Exp_Primary exp ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_array_lit() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ) { // verify there are no errors from the parser... if( !verify_array( exp->array ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_cast() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_cast( Chuck_Env * env, a_Exp_Cast cast ) { // check the exp t_CKBOOL t = type_engine_scan2_exp( env, cast->exp ); if( !t ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_dur() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_dur( Chuck_Env * env, a_Exp_Dur dur ) { // type check the two components t_CKBOOL base = type_engine_scan2_exp( env, dur->base ); t_CKBOOL unit = type_engine_scan2_exp( env, dur->unit ); // make sure both type check if( !base || !unit ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_postfix() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ) { // check the exp t_CKBOOL t = type_engine_scan2_exp( env, postfix->exp ); if( !t ) return FALSE; // syntax // TODO: figure out ++/-- switch( postfix->op ) { case ae_op_plusplus: case ae_op_minusminus: // assignable? if( postfix->exp->s_meta != ae_meta_var ) { EM_error2( postfix->exp->linepos, "postfix operator '%s' cannot be used on non-mutable data-type...", op2str( postfix->op ) ); return FALSE; } // TODO: mark somewhere we need to post increment return TRUE; break; default: // no match EM_error2( postfix->linepos, "internal compiler error (pre-scan): unrecognized postfix '%i'", postfix->op ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_if( Chuck_Env * env, a_Exp_If exp_if ) { // check the components t_CKBOOL cond = type_engine_scan2_exp( env, exp_if->cond ); t_CKBOOL if_exp = type_engine_scan2_exp( env, exp_if->if_exp ); t_CKBOOL else_exp = type_engine_scan2_exp( env, exp_if->else_exp ); // make sure everything good if( !cond || !if_exp || !else_exp ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_array_subscripts( ) // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_array_subscripts( Chuck_Env * env, a_Exp exp_list ) { return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_decl( ) // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl ) { a_Var_Decl_List list = decl->var_decl_list; a_Var_Decl var_decl = NULL; Chuck_Type * type = NULL; Chuck_Value * value = NULL; t_CKBOOL do_alloc = TRUE; // retrieve the type type = decl->ck_type; // make sure it's not NULL assert( type != NULL ); // check to see type is not void if( type->size == 0 ) { EM_error( decl->linepos, "cannot declare variables of size '0' (i.e. 'void')..." ); return FALSE; } // T @ foo? do_alloc = !decl->type->ref; // make sure complete if( /*!t->is_complete &&*/ do_alloc ) { // check to see if class inside itself if( env->class_def && equals( type, env->class_def ) && env->class_scope == 0 ) { EM_error2( decl->linepos, "...(note: object of type '%s' declared inside itself)", type->c_name() ); return FALSE; } } // primitive if( (isprim( type ) || isa( type, &t_string )) && decl->type->ref ) // TODO: string { EM_error2( decl->linepos, "cannot declare references (@) of primitive type '%s'...", type->c_name() ); EM_error2( decl->linepos, "...(primitive types: 'int', 'float', 'time', 'dur')" ); return FALSE; } // loop through the variables while( list != NULL ) { // get the decl var_decl = list->var_decl; // check if reserved if( type_engine_check_reserved( env, var_decl->xid, var_decl->linepos ) ) { EM_error2( var_decl->linepos, "...in variable declaration", S_name(var_decl->xid) ); return FALSE; } // check if locally defined if( env->curr->lookup_value( var_decl->xid, FALSE ) ) { EM_error2( var_decl->linepos, "'%s' has already been defined in the same scope...", S_name(var_decl->xid) ); return FALSE; } // check if array if( var_decl->array != NULL ) { // verify there are no errors from the parser... if( !verify_array( var_decl->array ) ) return FALSE; Chuck_Type * t2 = type; // may be partial and empty [] if( var_decl->array->exp_list ) { // scan2 the exp if( !type_engine_scan2_exp( env, var_decl->array->exp_list ) ) return FALSE; // make sure types are of int if( !type_engine_scan2_array_subscripts( env, var_decl->array->exp_list ) ) return FALSE; } // create the new array type type = new_array_type( env, // the env &t_array, // the array base class, usually &t_array var_decl->array->depth, // the depth of the new type t2, // the 'array_type' env->curr // the owner namespace ); // set ref if( !var_decl->array->exp_list ) decl->type->ref = TRUE; // set reference : decl->ck_type = type; SAFE_REF_ASSIGN( decl->ck_type, type ); } // enter into value binding env->curr->value.add( var_decl->xid, value = env->context->new_Chuck_Value( type, S_name(var_decl->xid) ) ); // remember the owner value->owner = env->curr; value->owner_class = env->func ? NULL : env->class_def; value->is_member = ( env->class_def != NULL && env->class_scope == 0 && env->func == NULL && !decl->is_static ); value->is_context_global = ( env->class_def == NULL && env->func == NULL ); value->addr = var_decl->addr; // flag it until the decl is checked value->is_decl_checked = FALSE; // remember the value var_decl->value = value; // the next var decl list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ) { // Chuck_Func * func = NULL; // Chuck_Func * up = NULL; // type check the func t_CKBOOL f = type_engine_scan2_exp( env, exp_func ); if( !f ) return FALSE; // check the arguments if( args ) { t_CKBOOL a = type_engine_scan2_exp( env, args ); if( !a ) return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ) { // type check it return type_engine_scan2_exp_func_call( env, func_call->func, func_call->args, func_call->ck_func, func_call->linepos ); } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_dot_member() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ) { // type check the base t_CKBOOL base = type_engine_scan2_exp( env, member->base ); if( !base ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_exp_array() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_exp_array( Chuck_Env * env, a_Exp_Array array ) { // verify there are no errors from the parser... if( !verify_array( array->indices ) ) return FALSE; // type check the base t_CKBOOL base = type_engine_scan2_exp( env, array->base ); if( !base ) return FALSE; // type check the index t_CKBOOL index = type_engine_scan2_exp( env, array->indices->exp_list ); if( !index ) return FALSE; // cycle through each exp // a_Exp e = array->indices->exp_list; // count the dimension // t_CKUINT depth = 0; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_scan2_class_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def class_def ) { // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // the class Chuck_Type * the_class = class_def->type; // make sure assert( the_class != NULL ); // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: // already flagged as having a constructor or not ret = type_engine_scan2_stmt_list( env, body->section->stmt_list ); break; case ae_section_func: // do function ret = type_engine_scan2_func_def( env, body->section->func_def ); break; case ae_section_class: // do the class ret = type_engine_scan2_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_scan2_func_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def f ) { Chuck_Type * type = NULL; Chuck_Value * value = NULL; Chuck_Func * func = NULL; // Chuck_Type * parent = NULL; Chuck_Value * overload = NULL; // Chuck_Value * override = NULL; Chuck_Value * v = NULL; // Chuck_Func * parent_func = NULL; a_Arg_List arg_list = NULL; // t_CKBOOL parent_match = FALSE; string func_name = S_name(f->name); string orig_name = func_name; vector values; vector symbols; t_CKUINT count = 0; // t_CKBOOL has_code = FALSE; // use this for both user and imported // see if we are already in a function definition if( env->func != NULL ) { EM_error2( f->linepos, "nested function definitions are not (yet) allowed" ); return FALSE; } // make sure a code segment is in stmt - else we should push scope assert( !f->code || f->code->s_type == ae_stmt_code ); // look up the value in the current class (can shadow?) if(( overload = env->curr->lookup_value( f->name, FALSE ) )) { // if value if( !isa( overload->type, &t_function ) ) { EM_error2( f->linepos, "function name '%s' is already used by another value", S_name(f->name) ); return FALSE; } else { // overload if( !overload->func_ref ) { // error EM_error2( f->linepos, "internal error: missing function '%s'", overload->name.c_str() ); return FALSE; } } } // if overload if( overload ) { // make the new name func_name += "@" + itoa( ++overload->func_num_overloads ) + "@" + env->curr->name; } else { // make name using 0 func_name += "@0@" + env->curr->name; } // make sure a code segment is in stmt - else we should push scope assert( !f->code || f->code->s_type == ae_stmt_code ); // make a new func object func = env->context->new_Chuck_Func(); // set the name func->name = func_name; // reference the function definition func->def = f; // note whether the function is marked as member func->is_member = (f->static_decl != ae_key_static) && (env->class_def != NULL); // copy the native code, for imported functions if( f->s_type == ae_func_builtin ) { // we can emit code now func->code = new Chuck_VM_Code; // whether the function needs 'this' func->code->need_this = func->is_member; // set the function pointer func->code->native_func = (t_CKUINT)func->def->dl_func_ptr; } // make a new type for the function type = env->context->new_Chuck_Type(); type->xid = te_function; type->name = "[function]"; type->parent = &t_function; type->size = sizeof(void *); type->func = func; // make new value, with potential overloaded name value = env->context->new_Chuck_Value( type, func_name ); // it is const value->is_const = TRUE; // remember the owner value->owner = env->curr; value->owner_class = env->class_def; value->is_member = func->is_member; // is global context value->is_context_global = env->class_def == NULL; // remember the func value->func_ref = func; func->add_ref(); // add reference TODO: break cycle? // remember the value func->value_ref = value; value->add_ref(); // add reference TODO: break cycle? // set the func f->ck_func = func; func->add_ref(); // add reference // if overload if( overload ) { // add func->next = overload->func_ref->next; overload->func_ref->next = func; } // make sure assert( f->ret_type != NULL ); // primitive if( (isprim( f->ret_type ) /*|| isa( f->ret_type, &t_string )*/) && f->type_decl->ref ) // TODO: string { EM_error2( f->type_decl->linepos, "cannot declare references (@) of primitive type '%s'...", f->ret_type->c_name() ); EM_error2( f->type_decl->linepos, "...(primitive types: 'int', 'float', 'time', 'dur')" ); goto error; } // look up types for the function arguments arg_list = f->arg_list; // count count = 1; // make room for 'this' f->stack_depth = func->is_member ? sizeof(void *) : 0; // loop over arguments while( arg_list ) { // make sure the type is not NULL - it should have been // set in scan1_func_def()... assert( arg_list->type != NULL ); // make sure it's not void if( arg_list->type->size == 0 ) { EM_error2( arg_list->linepos, "cannot declare variables of size '0' (i.e. 'void')..." ); goto error; } // check if reserved if( type_engine_check_reserved( env, arg_list->var_decl->xid, arg_list->linepos ) ) { EM_error2( arg_list->linepos, "in function '%s'", S_name(f->name) ); goto error; } // look up in scope: later //if( env->curr->lookup_value( arg_list->var_decl->xid, FALSE ) ) //{ // EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) ); // EM_error2( arg_list->linepos, "argument %i '%s' is already defined in this scope", // count, S_name(arg_list->var_decl->xid) ); // goto error; //} // primitive if( (isprim( arg_list->type ) /*|| isa( arg_list->type, &t_string )*/) && arg_list->type_decl->ref ) // TODO: string { EM_error2( arg_list->type_decl->linepos, "cannot declare references (@) of primitive type '%s'...", arg_list->type->c_name() ); EM_error2( arg_list->type_decl->linepos, "...(primitive types: 'int', 'float', 'time', 'dur')" ); goto error; } // check if array if( arg_list->var_decl->array != NULL ) { // verify there are no errors from the parser... if( !verify_array( arg_list->var_decl->array ) ) return FALSE; Chuck_Type * t = arg_list->type; Chuck_Type * t2 = t; // should be partial and empty [] if( arg_list->var_decl->array->exp_list ) { EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) ); EM_error2( arg_list->linepos, "argument %i '%s' must be defined with empty []'s", count, S_name(arg_list->var_decl->xid) ); return FALSE; } // create the new array type t = new_array_type( env, // the env &t_array, // the array base class, usually &t_array arg_list->var_decl->array->depth, // the depth of the new type t2, // the 'array_type' env->curr // the owner namespace ); // set ref arg_list->type_decl->ref = TRUE; // set type : arg_list->type = t; SAFE_REF_ASSIGN( arg_list->type, t ); } // make new value v = env->context->new_Chuck_Value( arg_list->type, S_name(arg_list->var_decl->xid) ); // remember the owner v->owner = env->curr; // function args not owned v->owner_class = NULL; v->is_member = FALSE; // later: add as value // symbols.push_back( arg_list ); // values.push_back( v ); // later: env->curr->value.add( arg_list->var_decl->xid, v ); // stack v->offset = f->stack_depth; f->stack_depth += arg_list->type->size; // remember arg_list->var_decl->value = v; // count count++; // next arg arg_list = arg_list->next; } // add as value env->curr->value.add( value->name, value ); // enter the name into the function table env->curr->func.add( func->name, func ); // add for orig name if( !overload ) { env->curr->value.add( orig_name, value ); env->curr->func.add( func->name, func ); } // if overload if( overload ) { // make sure returns are equal if( *(f->ret_type) != *(overload->func_ref->def->ret_type) ) { EM_error2( f->linepos, "function signatures differ in return type..." ); EM_error2( f->linepos, "function '%s.%s' matches '%s.%s' but cannot overload...", env->class_def->c_name(), S_name(f->name), value->owner_class->c_name(), S_name(f->name) ); goto error; } } // set the current function to this env->func = func; // push the value stack env->curr->value.push(); // scan the code assert( f->code == NULL || f->code->s_type == ae_stmt_code ); if( f->code && !type_engine_scan2_code_segment( env, &f->code->stmt_code, FALSE ) ) { EM_error2( 0, "...in function '%s'", S_name(f->name) ); goto error; } // pop the value stack env->curr->value.pop(); // clear the env's function definition env->func = NULL; return TRUE; error: // clean up if( func ) { env->func = NULL; func->release(); } return FALSE; } chuck-1.2.0.8.dfsg/src/chuck_scan.h0000644000175000017500000000572110600421721015404 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_scan.h // desc: chuck type-system / type-checker pre-scan // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 - original //----------------------------------------------------------------------------- #ifndef __CHUCK_SCAN_H__ #define __CHUCK_SCAN_H__ #include "chuck_type.h" // scan a program into the env - type discovery scan t_CKBOOL type_engine_scan0_prog( Chuck_Env * env, a_Program prog, te_HowMuch val = te_do_all ); // scan a class definition (used by type_engine_add_dll()) t_CKBOOL type_engine_scan0_class_def( Chuck_Env * env, a_Class_Def def ); // scan a program into the env - type resolution scan t_CKBOOL type_engine_scan1_prog( Chuck_Env * env, a_Program prog, te_HowMuch val = te_do_all ); // scan a class definition (used by type_engine_add_dll()) t_CKBOOL type_engine_scan1_class_def( Chuck_Env * env, a_Class_Def def ); // scan a function definition (used by type_engine_add_dll()) t_CKBOOL type_engine_scan1_func_def( Chuck_Env * env, a_Func_Def def ); // scan an exp decl t_CKBOOL type_engine_scan1_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); // scan a program into the env - function/member/static scan t_CKBOOL type_engine_scan2_prog( Chuck_Env * env, a_Program prog, te_HowMuch val = te_do_all ); // scan a class definition (used by type_engine_add_dll()) t_CKBOOL type_engine_scan2_class_def( Chuck_Env * env, a_Class_Def def ); // scan a function definition (used by type_engine_add_dll()) t_CKBOOL type_engine_scan2_func_def( Chuck_Env * env, a_Func_Def def ); // scan an exp decl t_CKBOOL type_engine_scan2_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); // the rest is done in chuck_type #endif chuck-1.2.0.8.dfsg/src/chuck_shell.cpp0000644000175000017500000017035410600421721016127 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_shell.cpp // desc: ... // // author: Spencer Salazar (ssalazar@princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #include "chuck_shell.h" #include "chuck_otf.h" #include "util_network.h" #include #include #include #ifndef __PLATFORM_WIN32__ #include #include #include #include #endif using namespace std; // global shell pointer (lives in chuck_main) extern Chuck_Shell * g_shell; //----------------------------------------------------------------------------- // name: tokenize_string // desc: divides a string into space separated tokens, respecting single and // double quotes //----------------------------------------------------------------------------- void tokenize_string( string str, vector< string > & tokens) { t_CKINT space = 1; t_CKINT end_space = 0; t_CKINT squote = 0; t_CKINT dquote = 0; t_CKINT i = 0, j = 0, len = str.size(); for( i = 0; i < len; i++ ) { if( isspace( str[i] ) && space ) { j++; continue; } if( isspace( str[i] ) && end_space ) { tokens.push_back( string( str, j, i - j ) ); j = i + 1; space = 1; end_space = 0; continue; } if( str[i] == '\'' ) { if( dquote ) continue; if( !squote ) { str.erase( i, 1 ); len--; i--; space = 0; end_space = 0; squote = 1; continue; } else if( str[i - 1] == '\\' ) { str.erase( i - 1, 1 ); len--; i--; continue; } else { str.erase( i, 1 ); len--; i--; squote = 0; end_space = 1; space = 0; continue; } } if( str[i] == '"' ) //" { if( squote ) continue; if( !dquote ) { str.erase( i, 1 ); i--; len--; space = 0; end_space = 0; dquote = 1; continue; } else if( str[i - 1] == '\\' ) { str.erase( i - 1, 1 ); len--; i--; continue; } else { str.erase( i, 1 ); i--; len--; dquote = 0; end_space = 1; space = 0; continue; } } if( !squote && !dquote ) { end_space = 1; space = 0; } } if( i > j && end_space ) { tokens.push_back( string( str, j, i - j ) ); } } //----------------------------------------------------------------------------- // name: shell_cb // desc: thread routine //----------------------------------------------------------------------------- void * shell_cb( void * p ) { Chuck_Shell * shell; // log EM_log( CK_LOG_INFO, "starting thread routine for shell..." ); // assuming this is absolutely necessary, an assert may be better assert( p != NULL ); shell = ( Chuck_Shell * ) p; //atexit( wait_for_shell ); // run the shell shell->run(); // delete and set to NULL SAFE_DELETE( g_shell ); // perhaps let shell destructor clean up mode and ui? EM_log( CK_LOG_INFO, "exiting thread routine for shell..." ); return NULL; } //----------------------------------------------------------------------------- // name: Chuck_Shell() // desc: ... //----------------------------------------------------------------------------- Chuck_Shell::Chuck_Shell() { ui = NULL; process_vm = NULL; current_vm = NULL; initialized = FALSE; stop = FALSE; code_entry_active = FALSE; } //----------------------------------------------------------------------------- // name: ~Chuck_Shell() // desc: ... //----------------------------------------------------------------------------- Chuck_Shell::~Chuck_Shell() { vector::size_type i, len = allocated_commands.size(); //iterate through commands, delete the associated heap data for( i = 0; i != len; i++ ) SAFE_DELETE( allocated_commands[i] ); // delete ui SAFE_DELETE( ui ); // flag initialized = FALSE; } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell::init( Chuck_VM * vm, Chuck_Shell_UI * ui ) { // log EM_log( CK_LOG_SYSTEM, "initializing chuck shell..." ); // check if( initialized == TRUE ) { EM_log( CK_LOG_WARNING, "chuck shell already initialized" ); return TRUE; } // ui if( ui == NULL ) { fprintf( stderr, "[chuck](via shell): NULL ui passed to Chuck_Shell::init..." ); return FALSE; } this->ui = ui; process_vm = vm; Chuck_Shell_Network_VM * cspv = new Chuck_Shell_Network_VM(); if( !cspv->init( "localhost", 8888 ) ) { fprintf( stderr, "[chuck](via shell): error initializing process VM..." ); SAFE_DELETE( cspv ); return FALSE; } current_vm = cspv; vms.push_back( current_vm->copy() ); process_vm = vm; code_entry_active = FALSE; code = ""; // init default variables variables["COMMAND_PROMPT"] = "chuck %> "; variables["DEFAULT_CONTEXT"] = "shell_global"; // initialize prompt prompt = variables["COMMAND_PROMPT"]; Command * temp; // initialize the string -> Chuck_Shell_Command map temp = new Command_VM(); temp->init( this ); commands["vm"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMList(); temp->init( this ); commands["vms"] = temp; allocated_commands.push_back( temp ); temp = new Command_Add(); temp->init( this ); commands["+"] = temp; commands["add"] = temp; allocated_commands.push_back( temp ); temp = new Command_Remove(); temp->init( this ); commands["-"] = temp; commands["remove"] = temp; allocated_commands.push_back( temp ); temp = new Command_Status(); temp->init( this ); commands["status"] = temp; commands["^"] = temp; allocated_commands.push_back( temp ); temp = new Command_Removeall(); temp->init( this ); commands["removeall"] = temp; allocated_commands.push_back( temp ); temp = new Command_Removelast(); temp->init( this ); commands["--"] = temp; allocated_commands.push_back( temp ); temp = new Command_Replace(); temp->init( this ); commands["replace"] = temp; commands["="] = temp; allocated_commands.push_back( temp ); temp = new Command_Close(); temp->init( this ); commands["close"] = temp; allocated_commands.push_back( temp ); temp = new Command_Kill(); temp->init( this ); commands["kill"] = temp; allocated_commands.push_back( temp ); temp = new Command_Exit(); temp->init( this ); commands["exit"] = temp; commands["quit"] = temp; allocated_commands.push_back( temp ); temp = new Command_Ls(); temp->init( this ); commands["ls"] = temp; allocated_commands.push_back( temp ); temp = new Command_Pwd(); temp->init( this ); commands["pwd"] = temp; allocated_commands.push_back( temp ); temp = new Command_Cd(); temp->init( this ); commands["cd"] = temp; allocated_commands.push_back( temp ); temp = new Command_Alias(); temp->init( this ); commands["alias"] = temp; allocated_commands.push_back( temp ); temp = new Command_Unalias(); temp->init( this ); commands["unalias"] = temp; allocated_commands.push_back( temp ); temp = new Command_Source(); temp->init( this ); commands["source"] = temp; commands["."] = temp; allocated_commands.push_back( temp ); temp = new Command_Code(); temp->init( this ); commands["code"] = temp; allocated_commands.push_back( temp ); // flag initialized = TRUE; return TRUE; } //----------------------------------------------------------------------------- // name: run() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::run() { // log EM_log( CK_LOG_SYSTEM, "running chuck shell..." ); // make sure if(initialized == FALSE) { fprintf( stderr, "[chuck](via shell): shell not initialized...\n" ); return; } string command; string result; ui->next_result( "welcome to chuck shell!\n" ); // ui->next_result( "(type \"help\" for more information)\n" ); // loop for( ; !stop; ) { // get command if( ui->next_command( prompt, command ) == TRUE ) { // result.clear(); result = ""; //printf( "chuck_shell::run\n" ); // execute the command execute( command, result ); // command.clear(); command = ""; // pass the result to the shell ui ui->next_result( result ); } else // done break; } // log EM_log( CK_LOG_SYSTEM, "exiting chuck shell..." ); } //----------------------------------------------------------------------------- // name: execute // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell::execute( string & in, string & out ) { if( !initialized ) { //fprintf(); return FALSE; } // vector of string tokens vector< string > vec; // clear the response out = ""; // first find out if this is code to run if( !code_entry_active && in[in.find_first_not_of( " \t\v\n" )] == '{' ) start_code(); if( code_entry_active ) { continue_code( in ); if( code_entry_active == FALSE ) { //strip opening and closing braces string::size_type k = code.find( "{" ); string head = string( code, 0, k ); code = string( code, k + 1, code.size() - k - 1 ); k = code.rfind( "}" ); string tail = string( code, k + 1, code.size() - k - 1 ); code = string( code, 0, k ); do_code( code, out ); tokenize_string( tail, vec ); if( vec.size() > 0 ) { string temp = "code save " + vec[0]; execute( temp, out ); } } return TRUE; } // divide the string into white space separated substrings tokenize_string( in, vec ); // if no tokens if( vec.size() == 0) return TRUE; // first check if the first token matches an alias while( aliases.find( vec[0] ) != aliases.end() ) // use a while loop to handle nested aliases { vector< string > vec2; tokenize_string( aliases[vec[0]], vec2 ); vec.erase( vec.begin() ); vec2.insert( vec2.end(), vec.begin(), vec.end() ); vec = vec2; } // locate the command if( commands.find( vec[0] ) == commands.end() ) // command doesn't exist! { out += vec[0] + ": command not found\n"; return FALSE; } else // execute the command { Command * command = commands[vec[0]]; vec.erase( vec.begin() ); if( command->execute( vec, out ) == 0 ) return TRUE; else return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: start_code() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::start_code() { code = ""; code_entry_active = TRUE; scope = 0; } //----------------------------------------------------------------------------- // name: continue_code() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::continue_code( string & in ) { if( in.find( "{" ) != string::npos ) // increase the scope one level and change the prompt { char buf[16]; scope++; #ifndef __PLATFORM_WIN32__ snprintf( buf, 16, "code %2d> ", (int)scope ); #else sprintf( buf, "code %2d> ", scope); #endif prompt = buf; } if( in.find( "}" ) != string::npos ) // decrease the scope one level and change the prompt { char buf[16]; scope--; #ifndef __PLATFORM_WIN32__ snprintf( buf, 16, "code %2d> ", (int)scope ); #else sprintf( buf, "code %2d> ", scope); #endif prompt = buf; } // collect this line as ChucK code code += in + "\n"; if( scope == 0 ) // the end of this code block -- lets execute it on the current_vm code_entry_active = FALSE; } //----------------------------------------------------------------------------- // name: do_code() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::do_code( string & code, string & out, string command ) { // open a temporary file #if defined(__LINUX_ALSA__) || defined(__LINUX_OSS__) || defined(__LINUX_JACK__) char tmp_dir[] = "/tmp"; char * tmp_filepath = new char [32]; strncpy( tmp_filepath, "/tmp/chuck_file.XXXXXX", 32 ); int fd = mkstemp( tmp_filepath ); if( fd == -1 ) { out += string( "shell: error: unable to create tmpfile at " ) + tmp_dir + "\n"; delete[] tmp_filepath; prompt = variables["COMMAND_PROMPT"]; return; } FILE * tmp_file = fdopen( fd, "w+" ); if( tmp_file == NULL ) { out += string( "shell: error: unable to reopen tmpfile at " ) + tmp_filepath + "\n"; delete[] tmp_filepath; prompt = variables["COMMAND_PROMPT"]; return; } #else char * tmp_filepath = tmpnam( NULL ); if( tmp_filepath == NULL ) { out += string( "shell: error: unable to generate tmpfile name\n" ); prompt = variables["COMMAND_PROMPT"]; return; } FILE * tmp_file = fopen( tmp_filepath, "w" ); if( tmp_file == NULL ) { out += string( "shell: error: unable to open tmpfile '" ) + tmp_filepath + "'\n"; prompt = variables["COMMAND_PROMPT"]; return; } #endif // write the code to the temp file fprintf( tmp_file, "%s", code.c_str() ); fclose( tmp_file ); string argv = string( command ) + tmp_filepath; this->execute( argv, out ); // if( this->execute( argv, out ) ) // ; // delete the file #ifndef __PLATFORM_WIN32__ unlink( tmp_filepath ); #else DeleteFile( tmp_filepath ); #endif // __PLATFORM_WIN32__ #if defined(__LINUX_ALSA__) || defined(__LINUX_OSS__) || defined(__LINUX_JACK__) delete[] tmp_filepath; #endif prompt = variables["COMMAND_PROMPT"]; } //----------------------------------------------------------------------------- // name: do_context() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::do_code_context( string & ) { } //----------------------------------------------------------------------------- // name: close() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::close() { stop = TRUE; // } //----------------------------------------------------------------------------- // name: kill() // desc: ... //----------------------------------------------------------------------------- void Chuck_Shell::exit() { stop = TRUE; if( process_vm != NULL ) process_vm->stop(); } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::init( const string & hostname, t_CKINT port ) { this->hostname = hostname; this->port = port; return TRUE; } //----------------------------------------------------------------------------- // name: copy() // desc: ... //----------------------------------------------------------------------------- Chuck_Shell_VM * Chuck_Shell_Network_VM::copy() { Chuck_Shell_Network_VM * net_vm = new Chuck_Shell_Network_VM(); net_vm->init( hostname, port ); return net_vm; } //----------------------------------------------------------------------------- // name: add_shred() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::add_shred( const vector< string > & files, string & out ) { t_CKINT i = 0; t_CKBOOL return_val; vector::size_type j, str_len, vec_len = files.size() + 1; char ** argv = new char * [ vec_len ]; /* prepare an argument vector to submit to otf_send_cmd */ /* first, specify an add command */ argv[0] = new char [2]; strncpy( argv[0], "+", 2 ); /* copy file paths into argv */ for( j = 1; j < vec_len; j++ ) { str_len = files[j - 1].size() + 1; argv[j] = new char [str_len]; strncpy( argv[j], files[j - 1].c_str(), str_len ); } /* send the command */ if( otf_send_cmd( vec_len, argv, i, hostname.c_str(), port ) ) return_val = TRUE; else { out += "add: error: command failed\n"; return_val = FALSE; } /* clean up heap data */ for( j = 0; j < vec_len; j++ ) delete[] argv[j]; delete[] argv; return return_val; } //----------------------------------------------------------------------------- // name: remove_shred() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::remove_shred( const vector< string > & ids, string & out ) { t_CKINT i = 0; t_CKBOOL return_val; vector::size_type j, str_len, vec_len = ids.size() + 1; char ** argv = new char * [ vec_len ]; /* prepare an argument vector to submit to otf_send_cmd */ /* first, specify an add command */ argv[0] = new char [2]; strncpy( argv[0], "-", 2 ); /* copy ids into argv */ for( j = 1; j < vec_len; j++ ) { str_len = ids[j - 1].size() + 1; argv[j] = new char [str_len]; strncpy( argv[j], ids[j - 1].c_str(), str_len ); } /* send the command */ if( otf_send_cmd( vec_len, argv, i, hostname.c_str(), port ) ) return_val = TRUE; else { out += "remove: error: command failed\n"; return_val = FALSE; } /* clean up heap data */ for( j = 0; j < vec_len; j++ ) delete[] argv[j]; delete[] argv; return return_val; } //----------------------------------------------------------------------------- // name: remove_all() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::remove_all( string & out ) { t_CKBOOL return_val = TRUE; t_CKINT j = 0; char ** argv = new char *; argv[0] = "--removeall"; if( !otf_send_cmd( 1, argv, j, hostname.c_str(), port ) ) { out += "removeall: error: command failed\n"; return_val = FALSE; } return return_val; } //----------------------------------------------------------------------------- // name: remove_last() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::remove_last( string & out ) { t_CKBOOL return_val = TRUE; t_CKINT j = 0; char ** argv = new char *; argv[0] = "--"; if( !otf_send_cmd( 1, argv, j, hostname.c_str(), port ) ) { out += "removelast: error: command failed\n"; return_val = FALSE; } return return_val; } //----------------------------------------------------------------------------- // name: replace_shred() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::replace_shred( const vector< string > &vec, string & out ) { if( vec.size() < 2 ) { out += "replace: error: insufficient arguments...\n"; return FALSE; } t_CKINT i = 0; t_CKBOOL return_val; vector::size_type j, str_len, vec_len = vec.size() + 1; char ** argv = new char * [ vec_len ]; /* prepare an argument vector to submit to otf_send_cmd */ /* first, specify an add command */ argv[0] = "--replace"; /* copy ids/files into argv */ for( j = 1; j < vec_len; j++ ) { str_len = vec[j - 1].size() + 1; argv[j] = new char [str_len]; strncpy( argv[j], vec[j - 1].c_str(), str_len ); } /* send the command */ if( otf_send_cmd( vec_len, argv, i, hostname.c_str(), port ) ) return_val = TRUE; else { out += "replace: error: command failed\n"; return_val = FALSE; } if( vec.size() % 2 != 0 ) { out += "repalce: warning: ignoring excess arguments\n"; return FALSE; } /* clean up heap data */ for( j = 1; j < vec_len; j++ ) delete[] argv[j]; delete[] argv; return return_val; } //----------------------------------------------------------------------------- // name: status() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::status( string & out ) { char ** argv = new char *; t_CKBOOL return_val = FALSE; t_CKINT j = 0; argv[0] = "--status"; if( otf_send_cmd( 1, argv, j, hostname.c_str(), port ) ) return_val = TRUE; else { return_val = FALSE; out += "status: error: command failed\n"; } delete argv; return return_val; } //----------------------------------------------------------------------------- // name: kill() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_Network_VM::kill( string & out ) { char ** argv = new char *; t_CKINT j = 0; t_CKBOOL return_val; argv[0] = "--kill"; if( otf_send_cmd( 1, argv, j, hostname.c_str(), port ) ) return_val = TRUE; else { return_val = FALSE; out += "kill: error: command failed"; } delete argv; return return_val; } //----------------------------------------------------------------------------- // name: fullname() // desc: returns a somewhat descriptive full name for this VM //----------------------------------------------------------------------------- string Chuck_Shell_Network_VM::fullname() { char buf[16]; sprintf( buf, ":%u", (int)port ); return hostname + buf; } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell_UI::init() { return TRUE; } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell::Command::init( Chuck_Shell * caller ) { this->caller = caller; return TRUE; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command::usage() { return "no usage specified"; } //----------------------------------------------------------------------------- // name: long_usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command::long_usage() { return "no usage specified"; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Add::execute( vector< string > & argv, string & out ) { t_CKINT result = 0; if( caller->current_vm == NULL) { out += "add: error: not attached to a VM\n"; result = -1; } else if( argv.size() < 1 ) { out += "usage: " + usage() + "\n"; result = -1; } else { result = caller->current_vm->add_shred( argv, out ); } return result; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Add::usage() { return "add file ..."; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Remove::execute( vector< string > & argv, string & out ) { t_CKINT result = 0; if( caller->current_vm == NULL) { out += "remove: error: not attached to a VM\n"; result = -1; } else if( argv.size() < 1 ) { out += "usage: " + usage() + "\n"; result = -1; } else result = caller->current_vm->remove_shred( argv, out ); return result; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Remove::usage() { return "remove shred_number ..."; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Removeall::execute( vector< string > & argv, string & out ) { t_CKINT result = 0; if( caller->current_vm == NULL) { out += "removeall: error: not attached to a VM\n"; result = -1; } else if( argv.size() > 0 ) { out += "usage " + usage() + "\n"; result = -1; } else result = caller->current_vm->remove_all( out ); return result; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Removeall::usage() { return "removeall"; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Removelast::execute( vector< string > & argv, string & out ) { t_CKINT result = -1; if( caller->current_vm == NULL) out += "removelast: error: not attached to a VM\n"; else result = caller->current_vm->remove_last( out ); if( argv.size() > 0 ) out += "removelast: warning: ignoring excess arguments...\n"; return result; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Removelast::usage() { return "removelast"; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Replace::execute( vector< string > & argv, string & out ) { if( caller->current_vm == NULL) { out += "replace: error: not attached to a VM\n"; return -1; } caller->current_vm->replace_shred( argv, out ); return 0; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Replace::usage() { return "replace shred_id file ..."; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Status::execute( vector< string > & argv, string & out ) { t_CKINT result = 0; if( caller->current_vm == NULL) { out += "status: error: not attached to a VM\n"; result = -1; } else if( argv.size() > 0 ) { out += "usage: " + usage() + "\n"; result = -1; } else result = caller->current_vm->status( out ); return result; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Status::usage() { return "status"; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Kill::execute( vector< string > & argv, string & out ) { caller->current_vm->kill( out ); if( argv.size() > 0 ) out += "kill: warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Close::execute( vector< string > & argv, string & out ) { caller->close(); out += "closing chuck shell... bye!\n"; if( g_shell != NULL ) out += "(note: in-process VM still running, hit ctrl-c to exit)\n"; if( argv.size() > 0 ) out += "close: warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Exit::execute( vector< string > & argv, string & out ) { caller->exit(); if( argv.size() > 0 ) out += "exit: warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Ls::execute( vector< string > & argv, string & out ) { #ifndef __PLATFORM_WIN32__ if( argv.size() == 0 ) { DIR * dir_handle = opendir( "." ); if( dir_handle == NULL ) { out += "ls: error: unable to open directory .\n"; return -1; } dirent * dir_entity = readdir( dir_handle ); while( dir_entity != NULL ) { out += string( dir_entity->d_name ) + "\n"; dir_entity = readdir( dir_handle ); } closedir( dir_handle ); return 0; } int i, len = argv.size(); t_CKBOOL print_parent_name = len > 1 ? TRUE : FALSE; for( i = 0; i < len; i++ ) { DIR * dir_handle = opendir( argv[i].c_str() ); if( dir_handle == NULL ) { out += "ls: error: unable to open directory " + argv[i] + "\n"; continue; } dirent * dir_entity = readdir( dir_handle ); if( print_parent_name ) out += argv[i] + ":\n"; while( dir_entity != NULL ) { out += string( dir_entity->d_name ) + "\n"; dir_entity = readdir( dir_handle ); } if( print_parent_name ) out += "\n"; closedir( dir_handle ); } #else if( argv.size() == 0 ) { DWORD i, k = 64; LPTSTR cwd = new char [k]; WIN32_FIND_DATA find_data; i = GetCurrentDirectory( k - 2, cwd ); if( i >= k ) { SAFE_DELETE_ARRAY( cwd ); cwd = new char [i + 2]; GetCurrentDirectory( i, cwd ); } i = strlen( cwd ); cwd[i] = '\\'; cwd[i + 1] = '*'; cwd[i + 2] = 0; HANDLE find_handle = FindFirstFile( cwd, &find_data ); out += string( find_data.cFileName ) + "\n"; while( FindNextFile( find_handle, &find_data ) ) out += string( find_data.cFileName ) + "\n"; FindClose( find_handle ); return 0; } int i, len = argv.size(); t_CKBOOL print_parent_name = len > 1 ? TRUE : FALSE; for( i = 0; i < len; i++ ) { int j = argv[i].size() + 3; WIN32_FIND_DATA find_data; LPTSTR dir = new char [j]; strncpy( dir, argv[i].c_str(), j ); dir[j - 3] = '\\'; dir[j - 2] = '*'; dir[j - 1] = 0; if( print_parent_name ) out += argv[i] + ":\n"; HANDLE find_handle = FindFirstFile( dir, &find_data ); out += string( find_data.cFileName ) + "\n"; while( FindNextFile( find_handle, &find_data ) ) out += string( find_data.cFileName ) + "\n"; if( print_parent_name ) out += "\n"; FindClose( find_handle ); } #endif // __PLATFORM_WIN32__ return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Cd::execute( vector< string > & argv, string & out ) { #ifndef __PLATFORM_WIN32__ if( argv.size() < 1 ) { if( chdir( getenv( "HOME" ) ) ) out += "cd: error: command failed\n"; } else { if( chdir( argv[0].c_str() ) ) out += "cd: error: command failed\n"; } #else if( argv.size() < 1 ) out += "usage: " + usage() + "\n"; else { if( !SetCurrentDirectory( argv[0].c_str() ) ) out += "cd: error: command failed\n"; } #endif //__PLATFORM_WIN32__ return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Pwd::execute( vector< string > & argv, string & out ) { #ifndef __PLATFORM_WIN32__ char * cwd = getcwd( NULL, 0 ); out += string( cwd ) + "\n"; free( cwd ); #else DWORD i, k = 256; LPTSTR cwd = new char [k]; i = GetCurrentDirectory( k, cwd ); if( i >= k ) { SAFE_DELETE_ARRAY( cwd ); cwd = new char [i]; GetCurrentDirectory( i, cwd ); } out += string( cwd ) + "\n"; SAFE_DELETE_ARRAY( cwd ); #endif if( argv.size() > 0 ) out += "pwd: warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Alias::execute( vector< string > & argv, string & out ) { vector::size_type i, len = argv.size(); string::size_type j; string a, b; for( i = 0; i < len; i++ ) { j = argv[i].find( "=" ); // no alias assignment specified; just print the alias value if exists if( j == string::npos ) { // see if the alias exists in the map if( caller->aliases.find( argv[i] ) == caller->aliases.end() ) out += "alias: error: alias " + argv[i] + " not found\n"; else out += "alias " + argv[i] + "='" + caller->aliases[argv[i]] + "'\n"; } // create the alias else { a = string( argv[i], 0, j ); b = string( argv[i], j + 1, string::npos ); caller->aliases[a] = b; } } if( len == 0 ) // no arguments specified; print the entire alias map { map< string, string>::iterator i = caller->aliases.begin(), end = caller->aliases.end(); for( ; i != end; i++ ) out += "alias " + i->first + "='" + i->second + "'\n"; } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Unalias::execute( vector< string > & argv, string & out ) { vector::size_type i, len = argv.size(); for( i = 0; i < len; i++ ) { if( caller->aliases.find( argv[i] ) == caller->aliases.end() ) out += "error: alias " + argv[i] + " not found\n"; else caller->aliases.erase( argv[i] ); } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Source::execute( vector< string > & argv, string & out ) { vector::size_type i, len = argv.size(); char line_buf[255]; string line, temp; for( i = 0; i < len; i++ ) { FILE * source_file = fopen( argv[i].c_str(), "r" ); if( source_file == NULL ) out += "error: unable to open file " + argv[i]; else { while( fgets( line_buf, 255, source_file ) != NULL ) { line = string( line_buf ); caller->execute( line, temp ); out += temp; } } } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Help::execute( vector< string > & argv, string & out ) { out += ""; return 0; } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell::Command_VM::init( Chuck_Shell * caller ) { Command * temp; Command::init( caller ); temp = new Command_VMAttach(); temp->init( caller ); commands["attach"] = temp; commands["@"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMAdd(); temp->init( caller ); commands["add"] = temp; commands["+"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMRemove(); temp->init( caller ); commands["remove"] = temp; commands["-"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMList(); temp->init( caller ); commands["list"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMSwap(); temp->init( caller ); commands["swap"] = temp; commands["<"] = temp; commands["<-"] = temp; allocated_commands.push_back( temp ); temp = new Command_VMAttachAdd(); temp->init( caller ); commands["@+"] = temp; allocated_commands.push_back( temp ); return TRUE; } //----------------------------------------------------------------------------- // name: ~Command_VM() // desc: ... //----------------------------------------------------------------------------- Chuck_Shell::Command_VM::~Command_VM() { vector::size_type i, len = allocated_commands.size(); //iterate through commands, delete the associated heap data for( i = 0; i != len; i++ ) SAFE_DELETE( allocated_commands[i] ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VM::execute( vector< string > & argv, string & out ) { if( argv.size() < 1) out += "usage: " + usage() + "\n"; else if( commands.find( argv[0] ) == commands.end() ) // command doesn't exist out += "error: vm " + argv[0] + ": command not found\n"; else // call the mapped command { Command * command = commands[argv[0]]; argv.erase( argv.begin() ); command->execute( argv, out ); } return 0; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_VM::usage() { return "vm [command] [args] ..."; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMAttach::execute( vector < string > & argv, string & out ) { string hostname; t_CKINT port; t_CKINT result = 0; /* parse the hostname:port */ if( argv.size() == 0 ) /* no hostname:port specified, use default */ { argv.push_back( "localhost:8888" ); hostname = "localhost"; port = 8888; } else { string::size_type i = argv[0].find( ":" ); if( i == string::npos ) // couldn't find a port number; use the default { hostname = argv[0]; port = 8888; argv[0] += ":8888"; } else { port = strtol( argv[0].c_str() + i + 1, NULL, 10 ); if( port == 0 ) out += string( "error: invalid port '" ) + string( argv[0].c_str() + i + 1 ) + "'\n"; else hostname = string( argv[0], 0, i ); } } if( port != 0 ) { //string temp; Chuck_Shell_Network_VM * new_vm = new Chuck_Shell_Network_VM(); new_vm->init( hostname, port ); /*if( !new_vm->status( temp ) ) { SAFE_DELETE( new_vm ); result = -1; }*/ SAFE_DELETE( caller->current_vm ); caller->current_vm = new_vm; out += argv[0] + " is now current VM\n"; result = 0; } else { out += "error: unable to attach to " + argv[0] + "\n"; result = -1; } if( argv.size() > 1 ) out += "warning: ignoring excess arguments...\n"; return result; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMAdd::execute( vector< string > & argv, string & out ) { char buf[16]; if( caller->current_vm == NULL ) { out += "error: no VM to save\n"; return -1; } caller->vms.push_back( caller->current_vm->copy() ); #ifndef __PLATFORM_WIN32__ snprintf( buf, 16, "%u", caller->vms.size() - 1 ); #else sprintf( buf, "%u", caller->vms.size() - 1 ); #endif // __PLATFORM_WIN32__ out += caller->current_vm->fullname() + " saved as VM " + buf + "\n"; if( argv.size() > 0 ) out += "warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMRemove::execute( vector< string > & argv, string & out ) { vector::size_type i = 0, vm_no, len = argv.size(); for( ; i < len; i++ ) { vm_no = strtoul( argv[i].c_str(), NULL, 10 ); if( vm_no == 0 && errno == EINVAL || caller->vms.size() <= vm_no || caller->vms[vm_no] == NULL ) { out += "error: invalid VM id: " + argv[i] + "\n"; } else { SAFE_DELETE( caller->vms[vm_no] ); } } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMSwap::execute( vector< string > & argv, string & out ) { vector::size_type new_vm = 0; if( argv.size() < 1 ) { out += string( "error: too few arguments...\n" ); return -1; } new_vm = strtol( argv[0].c_str(), NULL, 10 ); if( new_vm >= caller->vms.size() || new_vm < 0 || caller->vms[new_vm] == NULL ) { out += string( "error: invalid VM: " ) + argv[0] + "\n"; return -1; } SAFE_DELETE( caller->current_vm ); caller->current_vm = caller->vms[new_vm]->copy(); out += "current VM is now " + caller->current_vm->fullname() + "\n"; if( argv.size() > 1 ) out += "warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMList::execute( vector< string > & argv, string & out ) { char buf[16]; vector::size_type i, len = caller->vms.size(); if( caller->current_vm != NULL ) out += string("current VM: ") + caller->current_vm->fullname() + "\n"; for( i = 0; i < len; i++ ) { if( caller->vms[i] != NULL ) { #ifndef __PLATFORM_WIN32__ snprintf( buf, 16, "%u", i ); #else sprintf( buf, "%u", i ); #endif // __PLATFORM_WIN32__ out += string( "VM " ) + buf + ": " + caller->vms[i]->fullname() + "\n"; } } if( argv.size() > 0 ) out += "warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_VMAttachAdd::execute( vector< string > & argv, string & out ) { t_CKINT result = 0; string exec = string( "vm @ " ) + ( argv.size() > 0 ? argv[0] : "" ); if( caller->execute( exec, out ) ) { exec = "vm + "; if( caller->execute( exec, out ) ) result = 0; else result = -1; } else result = -1; return result; } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Shell::Command_Code::init( Chuck_Shell * caller ) { Command * temp; Command::init( caller ); temp = new Command_CodeSave(); temp->init( caller ); commands["save"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodeList(); temp->init( caller ); commands["list"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodePrint(); temp->init( caller ); commands["print"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodeDelete(); temp->init( caller ); commands["delete"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodeWrite(); temp->init( caller ); commands["write"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodeRead(); temp->init( caller ); commands["read"] = temp; allocated_commands.push_back( temp ); temp = new Command_CodeAdd(); temp->init( caller ); commands["add"] = temp; commands["+"] = temp; allocated_commands.push_back( temp ); return TRUE; } //----------------------------------------------------------------------------- // name: ~Command_Code() // desc: ... //----------------------------------------------------------------------------- Chuck_Shell::Command_Code::~Command_Code() { vector::size_type i, len = allocated_commands.size(); //iterate through commands, delete the associated heap data for( i = 0; i != len; i++ ) SAFE_DELETE( allocated_commands[i] ); } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_Code::execute( vector< string > & argv, string & out ) { if( argv.size() < 1) out += "usage: " + usage() + "\n"; else if( commands.find( argv[0] ) == commands.end() ) // command doesn't exist out += "error: code " + argv[0] + ": command not found\n"; else { // call the mapped command Command * command = commands[argv[0]]; argv.erase( argv.begin() ); command->execute( argv, out ); } return 0; } //----------------------------------------------------------------------------- // name: usage() // desc: ... //----------------------------------------------------------------------------- string Chuck_Shell::Command_Code::usage() { return "code [command] [args] ..."; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeSave::execute( vector < string > & argv, string & out ) { if( argv.size() < 1 ) { out += "error: please specify a name to identify the code\n"; } else { if( caller->code == "" ) out += "error: no code to save\n"; else caller->saved_code[argv[0]] = caller->code; if( argv.size() > 1 ) out += "warning: ignoring excess arguments...\n"; } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeList::execute( vector < string > & argv, string & out ) { map< string, string >::iterator i = caller->saved_code.begin(), end = caller->saved_code.end(); for( ; i != end; i++ ) out += i->first + "\n"; if( argv.size() > 0 ) out += "warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeAdd::execute( vector < string > & argv, string & out ) { if( argv.size() == 0 ) { if( caller->code != "" ) caller->do_code( caller->code, out ); else out += "error: no code to add\n"; } else { vector::size_type i, len; for( i = 0, len = argv.size(); i < len; i++ ) { // iterate through all of the arguments, add the saved codes if( caller->saved_code.find( argv[i] ) == caller->saved_code.end() ) out += "error: code " + argv[i] + " not found\n"; else caller->do_code( caller->code, out ); } } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodePrint::execute( vector < string > & argv, string & out ) { if( argv.size() == 0 ) { if( caller->code != "" ) out += caller->code + "\n"; else out += "error: no code to print\n"; } else { vector::size_type i, len; for( i = 0, len = argv.size(); i < len; i++ ) { if( caller->saved_code.find( argv[i] ) == caller->saved_code.end() ) { out += "error: code " + argv[i] + " not found\n"; } else { string code = caller->saved_code[argv[i]]; out += argv[i] + ":\n"; out += code + "\n"; } } } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeDelete::execute( vector < string > & argv, string & out ) { if( argv.size() == 0 ) { out += "error: specify the code to delete\n"; } else { vector::size_type i, len; for( i = 0, len = argv.size(); i < len; i++ ) { if( caller->saved_code.find( argv[i] ) == caller->saved_code.end() ) out += "error: code " + argv[i] + " not found\n"; else { caller->saved_code.erase( argv[i] ); } } } return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeWrite::execute( vector < string > & argv, string & out ) { if( argv.size() < 1 ) { out += "error: insufficient arguments...\n"; } else { if( caller->saved_code.find( argv[0] ) == caller->saved_code.end() ) { // this code doesnt exist! out += "error: code " + argv[0] + " not found\n"; } else { string filename; string code = caller->saved_code[argv[0]]; FILE * write_file; if( argv.size() >= 2 ) { // use second argument as filename filename = argv[1]; } else { // append .ck to the code name to get the file name filename = argv[0] + ".ck"; } // open the file write_file = fopen( filename.c_str(), "w" ); if( write_file == NULL ) { out += "error: unable to open " + filename + " for writing\n"; } else { // write code to the file if( fprintf( write_file, "%s", code.c_str() ) < 0 ) out += "error: unable to write to " + filename + "\n"; fclose( write_file ); } } } if( argv.size() > 2 ) out += "warning: ignoring excess arguments...\n"; return 0; } //----------------------------------------------------------------------------- // name: execute() // desc: ... //----------------------------------------------------------------------------- t_CKINT Chuck_Shell::Command_CodeRead::execute( vector < string > & argv, string & out ) { if( argv.size() < 1 ) { out += "error: insufficient arguments...\n"; } else { string code_name; FILE * read_file; if( argv.size() >= 2 ) { // use second argument as the code_name code_name = argv[1]; } else { // remove the file extension to get the code_name // or use the whole filename if there is no extension string::size_type k = argv[0].rfind( "." ); if( k == string::npos ) code_name = argv[1]; else code_name = string( argv[0], 0, k ); } // open the file read_file = fopen( argv[0].c_str(), "r" ); if( read_file == NULL ) out += "error: unable to open " + argv[0] + " for reading\n"; else { string code = ""; char buffer[256], * result = fgets( buffer, 256, read_file ); if( result == NULL ) out += "error: unable to read " + argv[0] + ", or file is empty\n"; else { while( result != NULL ) { code += buffer; result = fgets( buffer, 256, read_file ); } caller->saved_code[code_name] = code; } fclose( read_file ); } } if( argv.size() > 2 ) out += "warning: ignoring excess arguments...\n"; return 0; } chuck-1.2.0.8.dfsg/src/chuck_shell.h0000644000175000017500000004435610600421721015576 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_shell.h // desc: ... // // author: Spencer Salazar (ssalazar@princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #ifndef __CHUCK_SHELL_H__ #define __CHUCK_SHELL_H__ #include "chuck_def.h" #include "chuck_errmsg.h" #include "chuck_vm.h" #include #include #include using namespace std; // forward references class Chuck_Shell_VM; class Chuck_Shell_UI; typedef string Chuck_Shell_Request; typedef string Chuck_Shell_Response; //----------------------------------------------------------------------------- // name: class Chuck_Shell // desc: controller class for facilitating interaction between a shell UI and a // shell mode. //----------------------------------------------------------------------------- class Chuck_Shell { public: Chuck_Shell(); virtual ~Chuck_Shell(); t_CKBOOL init( Chuck_VM * process_vm, Chuck_Shell_UI * ); void run(); t_CKBOOL execute( string &, string & ); void close(); void exit(); public: // HACK-GE: these were moved from protected for win32 vector < Chuck_Shell_VM * > vms; Chuck_VM * process_vm; Chuck_Shell_VM * current_vm; //forward declaration class Command; // alias, variable, and command maps map < string, string > aliases; map < string, string > variables; map < string, Command * > commands; vector < Command * > allocated_commands; map < string, string > saved_code; string code; // helper functions t_CKBOOL do_glob( const string &, string &, vector < string > & ); void do_code( string &, string &, string command = "+ " ); void do_code_context( string & ); protected: // helper functions void do_aliases(); void do_variables(); // code helper functions void start_code(); void continue_code( string & ); void string_hash( string &, string & ); Chuck_Shell_UI * ui; t_CKBOOL initialized; t_CKBOOL stop; string prompt; string in; // code entry variables t_CKBOOL code_entry_active; t_CKUINT scope; public: // HACK-GE: moved from protected for win32 //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command // desc: superclass to Chuck_Shell_Commands //----------------------------------------------------------------------------- class Command { public: // virtual destructor (gewang) virtual ~Command() { } public: virtual t_CKBOOL init( Chuck_Shell * ); virtual t_CKINT execute( vector< string > &, string & ) = 0; virtual string usage(); virtual string long_usage(); protected: Chuck_Shell * caller; }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM // desc: ... //----------------------------------------------------------------------------- class Command_VM : public Command { public: ~Command_VM(); t_CKBOOL init( Chuck_Shell * ); t_CKINT execute( vector< string > &, string & ); string usage(); protected: map < string, Command * > commands; vector < Command * > allocated_commands; }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_Add // desc: ... //----------------------------------------------------------------------------- class Command_VMAdd : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_Remove // desc: ... //----------------------------------------------------------------------------- class Command_VMRemove : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_Attach // desc: ... //----------------------------------------------------------------------------- class Command_VMAttach : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_List // desc: ... //----------------------------------------------------------------------------- class Command_VMList : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_Swap // desc: ... //----------------------------------------------------------------------------- class Command_VMSwap : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_VM_AttachAdd // desc: ... //----------------------------------------------------------------------------- class Command_VMAttachAdd : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Add // desc: ... //----------------------------------------------------------------------------- class Command_Add : public Command { public: t_CKINT execute( vector < string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Remove // desc: ... //----------------------------------------------------------------------------- class Command_Remove : public Command { public: t_CKINT execute( vector < string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Status // desc: ... //----------------------------------------------------------------------------- class Command_Status : public Command { public: t_CKINT execute( vector < string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Removeall // desc: ... //----------------------------------------------------------------------------- class Command_Removeall : public Command { public: t_CKINT execute( vector< string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Removelast // desc: ... //----------------------------------------------------------------------------- class Command_Removelast : public Command { public: t_CKINT execute( vector< string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Replace // desc: ... //----------------------------------------------------------------------------- class Command_Replace : public Command { public: t_CKINT execute( vector< string > &, string & ); string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Kill // desc: ... //----------------------------------------------------------------------------- class Command_Kill : public Command { public: t_CKINT execute( vector< string > &, string & ); //string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Close // desc: ... //----------------------------------------------------------------------------- class Command_Close : public Command { public: t_CKINT execute( vector< string > &, string & ); //string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Exit // desc: ... //----------------------------------------------------------------------------- class Command_Exit : public Command { public: t_CKINT execute( vector< string > &, string & ); //string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Ls // desc: ... //----------------------------------------------------------------------------- class Command_Ls : public Command { public: t_CKINT execute( vector< string > &, string & ); //string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Cd // desc: ... //----------------------------------------------------------------------------- class Command_Cd : public Command { public: t_CKINT execute( vector< string > &, string & ); //string usage(); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Pwd // desc: ... //----------------------------------------------------------------------------- class Command_Pwd : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Alias // desc: ... //----------------------------------------------------------------------------- class Command_Alias : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Unalias // desc: ... //----------------------------------------------------------------------------- class Command_Unalias : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Source // desc: ... //----------------------------------------------------------------------------- class Command_Source : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Code // desc: ... //----------------------------------------------------------------------------- class Command_Code : public Command { public: ~Command_Code(); t_CKBOOL init( Chuck_Shell * ); t_CKINT execute( vector< string > &, string & ); string usage(); private: map < string, Command * > commands; vector < Command * > allocated_commands; }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeContext // desc: ... //----------------------------------------------------------------------------- class Command_CodeContext : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeSave // desc: ... //----------------------------------------------------------------------------- class Command_CodeSave : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeDelete // desc: ... //----------------------------------------------------------------------------- class Command_CodeDelete : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeAdd // desc: ... //----------------------------------------------------------------------------- class Command_CodeAdd : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeList // desc: ... //----------------------------------------------------------------------------- class Command_CodeList : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodePrint // desc: ... //----------------------------------------------------------------------------- class Command_CodePrint : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeWrite // desc: ... //----------------------------------------------------------------------------- class Command_CodeWrite : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_CodeRead // desc: ... //----------------------------------------------------------------------------- class Command_CodeRead : public Command { public: t_CKINT execute( vector< string > &, string & ); }; //----------------------------------------------------------------------------- // name: class Chuck_Shell::Command_Help // desc: ... //----------------------------------------------------------------------------- class Command_Help : public Command { public: t_CKINT execute( vector< string > &, string & ); }; }; //----------------------------------------------------------------------------- // name: class Chuck_Shell_VM // desc: encapsulates local and network VMs into a single class //----------------------------------------------------------------------------- class Chuck_Shell_VM { public: virtual ~Chuck_Shell_VM() {} public: virtual Chuck_Shell_VM * copy()=0; virtual t_CKBOOL add_shred( const vector< string > &, string & )=0; virtual t_CKBOOL remove_shred( const vector< string > &, string & )=0; virtual t_CKBOOL remove_all( string & )=0; virtual t_CKBOOL remove_last( string & )=0; virtual t_CKBOOL replace_shred( const vector< string > &, string & )=0; virtual t_CKBOOL status( string & )=0; virtual t_CKBOOL kill( string & )=0; virtual string fullname()=0; }; //----------------------------------------------------------------------------- // name: class Chuck_Shell_Network_VM // desc: VM across the network //----------------------------------------------------------------------------- class Chuck_Shell_Network_VM : public Chuck_Shell_VM { public: virtual ~Chuck_Shell_Network_VM() {} public: Chuck_Shell_VM * copy(); t_CKBOOL init( const string &, t_CKINT ); t_CKBOOL add_shred( const vector< string > &, string & ); t_CKBOOL remove_shred( const vector< string > &, string & ); t_CKBOOL remove_all( string & ); t_CKBOOL remove_last( string & ); t_CKBOOL replace_shred( const vector< string > &, string & ); t_CKBOOL status( string & ); t_CKBOOL kill( string & ); string fullname(); private: string hostname; t_CKINT port; }; /* //----------------------------------------------------------------------------- // name: class Chuck_Shell_Network_VM // desc: VM across the network //----------------------------------------------------------------------------- class Chuck_Shell_Process_VM : public Chuck_Shell_VM { public: virtual ~Chuck_Shell_Process_VM() {} public: Chuck_Shell_VM * copy(); t_CKBOOL init( const string &, t_CKINT ); t_CKBOOL add_shred( const vector< string > &, string & ); t_CKBOOL remove_shred( const vector< string > &, string & ); t_CKBOOL remove_all( string & ); t_CKBOOL remove_last( string & ); t_CKBOOL replace_shred( const vector< string > &, string & ); t_CKBOOL status( string & ); t_CKBOOL kill( string & ); string fullname(); t_CKUINT last_shred_id(); private: Chuck_VM * vm; Chuck_Compiler * compiler; }; */ //----------------------------------------------------------------------------- // name: class Chuck_Shell_UI // desc: superclass to various types of Chuck UIs //----------------------------------------------------------------------------- class Chuck_Shell_UI { public: virtual ~Chuck_Shell_UI() {} public: virtual t_CKBOOL init(); virtual t_CKBOOL next_command( const string &, string & ) = 0; virtual void next_result( const string & ) = 0; }; // prototype for shell thread routine void * shell_cb( void * p ); #endif //__CHUCK_SHELL_H__ chuck-1.2.0.8.dfsg/src/chuck_stats.cpp0000644000175000017500000002025610600421721016151 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_stats.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip Davidson (philipd@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Autumn 2004 //----------------------------------------------------------------------------- #include "chuck_stats.h" // tracking #if defined(__CHUCK_STAT_TRACK__) #include "chuck_vm.h" using namespace std; // static members Chuck_Stats * Chuck_Stats::our_instance = NULL; t_CKBOOL Chuck_Stats::activations_yes = FALSE; //----------------------------------------------------------------------------- // name: instance() // desc: ... //----------------------------------------------------------------------------- Chuck_Stats * Chuck_Stats::instance() { if( !our_instance ) { our_instance = new Chuck_Stats; assert( our_instance ); } return our_instance; } //----------------------------------------------------------------------------- // name: add_shred() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::add_shred( Chuck_VM_Shred * shred ) { assert( vm != NULL ); assert( shred->stat == NULL ); assert( shred->xid != 0 ); Shred_Stat * stat = new Shred_Stat; stat->xid = shred->xid; stat->parent = shred->parent ? shred->parent->xid : 0; stat->state = 0; // inactive stat->shred_ref = shred; stat->spork_time = shred->wake_time; stat->wake_time = shred->wake_time; stat->name = shred->name; stat->owner = "noone"; stat->source = "remote"; if( strncmp( shred->name.c_str(), "editor->", 8 ) == 0 ) { stat->name = shred->name.c_str() + 8; stat->source = "editor"; } if( shred->parent ) { Shred_Stat * another = shreds[shred->parent->xid]; another->mutex.acquire(); another->children.push_back( stat ); another->mutex.release(); } // attach to shred shred->stat = stat; // add mutex.acquire(); shreds[shred->xid] = stat; mutex.release(); } //----------------------------------------------------------------------------- // name: activate_shred() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::activate_shred( Chuck_VM_Shred * shred ) { assert( vm != NULL ); //assert( shred->stat != NULL ); //assert( shred->id != 0 ); Shred_Stat * stat = shred->stat; // set active state stat->state = 1; // active // increment activations stat->activations++; // set the active time stat->active_time = shred->wake_time; } //----------------------------------------------------------------------------- // name: advance_time() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::advance_time( Chuck_VM_Shred * shred, t_CKTIME to ) { assert( vm != NULL ); Shred_Stat * stat = shred->stat; // set the wake_time stat->wake_time = to; // find the period t_CKDUR diff = stat->wake_time - stat->active_time; // add to diffs stat->diff_total += diff; // put in queue stat->diffs.push( diff ); // subtract if( stat->diffs.size() > stat->num_diffs ) { stat->diff_total -= stat->diffs.front(); stat->diffs.pop(); } // calculate average stat->average_ctrl = stat->diff_total / stat->diffs.size(); } //----------------------------------------------------------------------------- // name: deactivate_shred() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::deactivate_shred( Chuck_VM_Shred * shred ) { assert( vm != NULL ); Shred_Stat * stat = shred->stat; // get diff t_CKUINT diff = stat->cycles - stat->last_cycles; // set active state stat->state = 2; // find average stat->act_cycles.push( diff ); // add to total stat->act_cycles_total += diff; // subtract if( stat->act_cycles.size() > stat->num_diffs ) { stat->act_cycles_total -= stat->act_cycles.front(); stat->act_cycles.pop(); } // the average stat->average_cycles = (t_CKFLOAT)stat->act_cycles_total / stat->act_cycles.size(); // remember the cycle count stat->last_cycles = stat->cycles; if( activations_yes ) { stat->mutex.acquire(); stat->activationss.push_back( Shred_Activation( vm->shreduler()->now_system, diff ) ); stat->mutex.release(); } } //----------------------------------------------------------------------------- // name: remove_shred() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::remove_shred( Chuck_VM_Shred * shred ) { assert( vm != NULL ); Shred_Stat * stat = shred->stat; // set state stat->state = 3; // deleted // set free time stat->free_time = vm->shreduler()->now_system; // remove mutex.acquire(); shreds.erase( shreds.find( stat->xid ) ); done.push_back( stat ); mutex.release(); } //----------------------------------------------------------------------------- // name: get_shreds() // desc: ... //----------------------------------------------------------------------------- void Chuck_Stats::get_shreds( vector & out, map & d ) { assert( vm != NULL ); map::iterator iter; out.clear(); mutex.acquire(); for( iter = shreds.begin(); iter != shreds.end(); iter++ ) out.push_back( (*iter).second ); for( int i = 0; i < done.size(); i++ ) d[done[i]] = done[i]; done.clear(); mutex.release(); } //----------------------------------------------------------------------------- // name: Chuck_Stats() // desc: ... //----------------------------------------------------------------------------- Chuck_Stats::Chuck_Stats() { vm = NULL; } //----------------------------------------------------------------------------- // name: ~Chuck_Stats() // desc: ... //----------------------------------------------------------------------------- Chuck_Stats::~Chuck_Stats() { } //----------------------------------------------------------------------------- // name: get_sporked() // desc: ... //----------------------------------------------------------------------------- void Shred_Stat::get_sporked( vector & out ) { out.clear(); mutex.acquire(); for( int i = 0; i < children.size(); i++ ) out.push_back( children[i] ); mutex.release(); } //----------------------------------------------------------------------------- // name: get_activations() // desc: ... //----------------------------------------------------------------------------- void Shred_Stat::get_activations( vector & out ) { out.clear(); mutex.acquire(); out = activationss; activationss.clear(); mutex.release(); } #endif chuck-1.2.0.8.dfsg/src/chuck_stats.h0000644000175000017500000001256710600421721015624 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_stats.h // desc: statistics - for audicle // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip Davidson (philipd@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Autumn 2004 //----------------------------------------------------------------------------- #ifndef __CHUCK_STATS_H__ #define __CHUCK_STATS_H__ #include "chuck_def.h" // tracking #if defined(__CHUCK_STAT_TRACK__) #include "util_thread.h" #include #include #include // forward reference struct Chuck_VM; struct Chuck_VM_Shred; struct Shred_Data; struct Shred_Time; //----------------------------------------------------------------------------- // name: struct Shred_Activation // desc: ... //----------------------------------------------------------------------------- struct Shred_Activation { t_CKTIME when; t_CKUINT cycles; Shred_Activation( t_CKTIME a, t_CKUINT b ) { when = a; cycles = b; } }; //----------------------------------------------------------------------------- // name: struct Shred_Stat // desc: ... //----------------------------------------------------------------------------- struct Shred_Stat { public: // instructions computed t_CKUINT cycles; // shred id t_CKUINT xid; // parent t_CKUINT parent; // current state, 0 = inactive, 1 = active, 2 = wait, 3 = deleted t_CKUINT state; // reference (could be pointing to garbage - see state) Chuck_VM_Shred * shred_ref; // number of activations t_CKUINT activations; // average control rate t_CKFLOAT average_ctrl; // average cycles t_CKFLOAT average_cycles; // spork time t_CKTIME spork_time; // active time t_CKTIME active_time; // wake time t_CKTIME wake_time; // free time t_CKTIME free_time; // name std::string name; // owner std::string owner; // source std::string source; // ctrl rate calculation std::queue diffs; // number of diffs t_CKUINT num_diffs; // total diffs t_CKDUR diff_total; // exe per activation std::queue act_cycles; // total t_CKUINT act_cycles_total; // last t_CKUINT last_cycles; // children std::vector children; void get_sporked( std::vector & out ); std::vector activationss; void get_activations( std::vector & out ); // mutex XMutex mutex; // audicle info Shred_Data * data; Shred_Time * time; public: Shred_Stat() { this->clear(); num_diffs = 8; data = NULL; time = NULL; } void clear() { xid = 0; parent = 0; state = 0; cycles = 0; activations = 0; average_ctrl = 0.0; spork_time = 0.0; active_time = 0.0; wake_time = 0.0; free_time = 0.0; name = "no name"; owner = "none"; source = "nowhere"; while( diffs.size() ) diffs.pop(); diff_total = 0.0; while( act_cycles.size() ) act_cycles.pop(); act_cycles_total = 0; last_cycles = 0; children.clear(); } }; //----------------------------------------------------------------------------- // name: struct Chuck_Stats // desc: ... //----------------------------------------------------------------------------- struct Chuck_Stats { public: static Chuck_Stats * instance(); public: void set_vm_ref( Chuck_VM * _vm ) { vm = _vm; } public: void add_shred( Chuck_VM_Shred * shred ); void activate_shred( Chuck_VM_Shred * shred ); void advance_time( Chuck_VM_Shred * shred, t_CKTIME to ); void deactivate_shred( Chuck_VM_Shred * shred ); void remove_shred( Chuck_VM_Shred * shred ); public: Shred_Stat * get_shred( t_CKUINT xid ) { mutex.acquire(); Shred_Stat * s = shreds[xid]; mutex.release(); return s; } void get_shreds( std::vector & out, std::map & d ); static t_CKBOOL activations_yes; protected: Chuck_Stats(); ~Chuck_Stats(); static Chuck_Stats * our_instance; protected: Chuck_VM * vm; std::map shreds; std::vector done; XMutex mutex; }; #endif #endif chuck-1.2.0.8.dfsg/src/chuck_symbol.cpp0000644000175000017500000000670210600421721016320 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_symbol.cpp // desc: ... // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_utils.h" #include "chuck_symbol.h" #include "chuck_table.h" // S_Symbol struct S_Symbol_ { c_str name; S_Symbol next; }; static S_Symbol mksymbol( c_constr name, S_Symbol next ) { S_Symbol s = (S_Symbol)checked_malloc(sizeof(*s)); s->name = (c_str)checked_malloc(strlen(name)+1); strcpy(s->name, (c_str)name); s->next=next; return s; } #define SIZE 65347 /* should be prime */ static S_Symbol hashtable[SIZE]; static unsigned int hash(const char *s0) { unsigned int h=0; const char *s; for(s=s0; *s; s++) h = h*65599 + *s; return h; } static int streq(c_constr a, c_constr b) { return !strcmp((char*)a,(char*)b); } S_Symbol insert_symbol(c_constr name) { S_Symbol syms = NULL, sym; int index= hash(name) % SIZE; if( !name ) return NULL; syms = hashtable[index]; for(sym=syms; sym; sym=sym->next) if (streq(sym->name,name)) return sym; sym = mksymbol(name,syms); hashtable[index]=sym; return sym; } c_str S_name( S_Symbol sym ) { return sym->name; } S_table S_empty( void ) { return TAB_empty(); } S_table S_empty2( unsigned int size ) { return TAB_empty2(size); } void S_enter( S_table t, S_Symbol sym, void *value ) { TAB_enter(t,sym,value); } void S_enter2( S_table t, c_constr str, void * value ) { TAB_enter(t,insert_symbol(str),value); } void * S_look( S_table t, S_Symbol sym ) { return TAB_look(t,sym); } void * S_look2( S_table t, c_constr str ) { return TAB_look(t,insert_symbol(str)); } static struct S_Symbol_ marksym = { "", 0 }; void S_beginScope( S_table t ) { S_enter( t, &marksym, NULL ); } void S_endScope( S_table t ) { S_Symbol s; do s = (S_Symbol)TAB_pop(t); while (s != &marksym); } void S_pop( S_table t ) { TAB_pop(t); } void S_dump( S_table t, void (*show)(S_Symbol sym, void *binding) ) { TAB_dump( t, (void (*)(void *, void *)) show ); } /* the str->whatever table */ chuck-1.2.0.8.dfsg/src/chuck_symbol.h0000644000175000017500000000552010600421721015762 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_symbol.h // desc: ... // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_SYMBOL_H__ #define __CHUCK_SYMBOL_H__ #include "chuck_utils.h" #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif typedef struct S_Symbol_ * S_Symbol; /* Make a unique symbol from a given c_str. * Different calls to make_symbol("foo") will yield the same S_Symbol * value, even if the "foo" c_str are at different locations. */ S_Symbol insert_symbol( c_constr ); /* Extract the underlying c_str from a symbol */ c_str S_name(S_Symbol); /* S_table is a mapping from S_Symbol->any, where "any" is represented * here by void* */ typedef struct TAB_table_ *S_table; /* Make a new table */ S_table S_empty(void); S_table S_empty2(unsigned int size); /* Enter a binding "sym->value" into "t", shadowing but not deleting * any previous binding of "sym". */ void S_enter(S_table t, S_Symbol sym, void * value); void S_enter2(S_table t, c_constr str, void * value); /* Look up the most recent binding of "sym" in "t", or return NULL * if sym is unbound. */ void * S_look(S_table t, S_Symbol sym); void * S_look2(S_table t, c_constr str); /* Start a new "scope" in "t". Scopes are nested. */ void S_beginScope(S_table t); /* Remove any bindings entered since the current scope began, and end the current scope. */ void S_endScope(S_table t); void S_pop(S_table t); #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/chuck_table.cpp0000644000175000017500000001273710600421721016107 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_table.cpp // desc: ... // // copyright (c) 1997 Andrew W. Appel. // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_table.h" #include "chuck_utils.h" #define TABSIZE 65437 typedef struct binder_ *binder; struct binder_ {void *key; void *value; binder next; void *prevtop;}; struct TAB_table_ { unsigned long size; binder * table; void * top; TAB_eq_func eq_func; TAB_hash_func hash_func; }; static binder Binder(void *key, void *value, binder next, void *prevtop) { binder b = (binder)checked_malloc(sizeof(struct binder_)); b->key = key; b->value=value; b->next=next; b->prevtop = prevtop; return b; } TAB_table TAB_empty(void) { return TAB_empty2(TABSIZE); } TAB_table TAB_empty2( unsigned long s ) { TAB_table t = (TAB_table)checked_malloc(sizeof(struct TAB_table_)); unsigned long i; t->table = (binder *)checked_malloc(sizeof(binder)*s); t->size = s; t->top = NULL; t->eq_func = NULL; t->hash_func = NULL; for( i = 0; i < s; i++ ) t->table[i] = NULL; return t; } TAB_table TAB_empty3( TAB_eq_func eq, TAB_hash_func hash, unsigned long s ) { TAB_table t = TAB_empty2(s); t->eq_func = eq; t->hash_func = hash; return t; } void TAB_delete( TAB_table t ) { unsigned long i; binder p = NULL, n = NULL; for(i = 0; i < t->size; i++ ) { p = t->table[i]; while( p ) { n = p->next; free(p); p = n; } } // free the table free( t->table ); free( t ); } /* The cast from pointer to integer in the expression * ((unsigned)key) % TABSIZE * may lead to a warning message. However, the code is safe, * and will still operate correctly. This line is just hashing * a pointer value into an integer value, and no matter how the * conversion is done, as long as it is done consistently, a * reasonable and repeatable index into the table will result. */ void TAB_enter(TAB_table t, void *key, void *value) { long index; unsigned long hval = (unsigned long)key; assert(t && key); if( t->hash_func ) hval = (unsigned long)t->hash_func(key); index = hval % t->size; t->table[index] = Binder(key, value, t->table[index], t->top); t->top = key; } void *TAB_look(TAB_table t, void *key) { long index; unsigned long hval = (unsigned long)key; binder b; assert(t && key); if( t->hash_func ) hval = (unsigned long)t->hash_func(key); index= hval % t->size; if( !t->eq_func ) { for(b=t->table[index]; b; b=b->next) if (b->key==key) return b->value; } else { for(b=t->table[index]; b; b=b->next) if (t->eq_func(b->key, key)) return b->value; } return NULL; } void *TAB_pop(TAB_table t) { void *k; binder b; long index; unsigned long hval; assert (t); k = t->top; assert (k); hval = (unsigned long)k; if(t->hash_func) hval = (unsigned long)t->hash_func(k); index = ((unsigned long)hval) % t->size; b = t->table[index]; assert(b); t->table[index] = b->next; t->top=b->prevtop; return b->key; } void *TAB_topv(TAB_table t) { void *k; binder b; long index; unsigned long hval; assert(t); k = t->top; assert(k); hval = (unsigned long)k; if(t->hash_func) hval = (unsigned long)t->hash_func(k); index = hval % t->size; b = t->table[index]; assert(b); return b->value; } void TAB_dump(TAB_table t, void (*show)(void *key, void *value)) { void *k = t->top; long index = ((unsigned long)k) % t->size; binder b = t->table[index]; if (b==NULL) return; t->table[index]=b->next; t->top=b->prevtop; show(b->key,b->value); TAB_dump(t,show); assert(t->top == b->prevtop && t->table[index]==b->next); t->top=k; t->table[index]=b; } long str_eq( void * lhs, void * rhs ) { return !strcmp( (char *)lhs, (char *)rhs ); } long str_hash( void * str ) { unsigned long h=0; char *s; for(s=(char *)str; *s; s++) h = h*65599 + *s; return h; } chuck-1.2.0.8.dfsg/src/chuck_table.h0000644000175000017500000000562610600421721015553 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_table.h // desc: ... // // No algorithm should use these functions directly, because // programming with void* is too error-prone. Instead, // each module should make "wrapper" functions that take // well-typed arguments and call the TAB_ functions. // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_TABLE_H__ #define __CHUCK_TABLE_H__ typedef struct TAB_table_ * TAB_table; typedef long (* TAB_eq_func)( void * lhs, void * rhs ); typedef long (* TAB_hash_func)( void * key ); /* Make a new table mapping "keys" to "values". */ TAB_table TAB_empty(void); TAB_table TAB_empty2(unsigned long size); TAB_table TAB_empty3( TAB_eq_func eq, TAB_hash_func hash, unsigned int size ); void TAB_delete( TAB_table t ); /* Enter the mapping "key"->"value" into table "t", * shadowing but not destroying any previous binding for "key". */ void TAB_enter(TAB_table t, void *key, void *value); /* Look up the most recent binding for "key" in table "t" */ void *TAB_look(TAB_table t, void *key); /* Pop the most recent binding and return its key. * This may expose another binding for the same key, if there was one. */ void *TAB_pop(TAB_table t); void *TAB_topv(TAB_table t); /* Call "show" on every "key"->"value" pair in the table, * including shadowed bindings, in order from the most * recent binding of any key to the oldest binding in the table */ void TAB_dump(TAB_table t, void (*show)(void *key, void *value)); /* str eq function */ long str_eq( void * lhs, void * rhs ); long str_hash( void * key ); #endif chuck-1.2.0.8.dfsg/src/chuck_type.cpp0000644000175000017500000046540510600421721016005 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_type.cpp // desc: chuck type-system / type-checker // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 - original // Autumn 2004 - rewrite //----------------------------------------------------------------------------- #include "chuck_type.h" #include "chuck_parse.h" #include "chuck_scan.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "chuck_lang.h" #include "util_string.h" #include "ugen_xxx.h" using namespace std; //----------------------------------------------------------------------------- // default types //----------------------------------------------------------------------------- Chuck_Type t_void( te_void, "void", NULL, 0 ); Chuck_Type t_int( te_int, "int", NULL, sizeof(t_CKINT) ); Chuck_Type t_float( te_float, "float", NULL, sizeof(t_CKFLOAT) ); Chuck_Type t_time( te_time, "time", NULL, sizeof(t_CKTIME) ); Chuck_Type t_dur( te_dur, "dur", NULL, sizeof(t_CKTIME) ); Chuck_Type t_null( te_null, "@null", NULL, sizeof(void *) ); Chuck_Type t_function( te_function, "@function", &t_object, sizeof(void *) ); Chuck_Type t_object( te_object, "Object", NULL, sizeof(void *) ); Chuck_Type t_array( te_array, "@array", &t_object, sizeof(void *) ); Chuck_Type t_string( te_string, "string", &t_object, sizeof(void *) ); Chuck_Type t_event( te_event, "Event", &t_object, sizeof(void *) ); Chuck_Type t_ugen( te_ugen, "UGen", &t_object, sizeof(void *) ); Chuck_Type t_shred( te_shred, "Shred", &t_object, sizeof(void *) ); Chuck_Type t_thread( te_thread, "Thread", &t_object, sizeof(void *) ); Chuck_Type t_class( te_class, "Class", &t_object, sizeof(void *) ); /* exile struct Chuck_Type t_adc = { te_adc, "adc", &t_ugen, t_ugen.size }; struct Chuck_Type t_dac = { te_dac, "dac", &t_ugen, t_ugen.size }; struct Chuck_Type t_bunghole = { te_bunghole, "bunghole", &t_ugen, t_ugen.size }; struct Chuck_Type t_midiout = { te_midiout, "midiout", &t_object, sizeof(void *) }; struct Chuck_Type t_midiin = { te_midiin, "midiin", &t_object, sizeof(void *) }; struct Chuck_Type t_stdout = { te_stdout, "@stdout", &t_object, sizeof(void *) }; struct Chuck_Type t_stderr ={ te_stdout, "@stderr", &t_object, sizeof(void *) }; struct Chuck_Type t_uint = { te_uint, "uint", NULL, sizeof(t_CKUINT) }; struct Chuck_Type t_single = { te_single, "single", NULL, sizeof(float) }; struct Chuck_Type t_double = { te_double, "double", NULL, sizeof(double) }; struct Chuck_Type t_code = { te_code, "code", NULL, sizeof(void *) }; struct Chuck_Type t_tuple = { te_tuple, "tuple", NULL, sizeof(void *) }; struct Chuck_Type t_pattern = { te_pattern, "pattern", &t_object, sizeof(void *) }; struct Chuck_Type t_transport = { te_transport, "transport", &t_object, sizeof(void *) }; struct Chuck_Type t_host = { te_host, "host", &t_object, sizeof(void *) }; */ //----------------------------------------------------------------------------- // function prototypes //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_stmt_list( Chuck_Env * env, a_Stmt_List list ); t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt ); t_CKBOOL type_engine_check_if( Chuck_Env * env, a_Stmt_If stmt ); t_CKBOOL type_engine_check_for( Chuck_Env * env, a_Stmt_For stmt ); t_CKBOOL type_engine_check_while( Chuck_Env * env, a_Stmt_While stmt ); t_CKBOOL type_engine_check_until( Chuck_Env * env, a_Stmt_Until stmt ); t_CKBOOL type_engine_check_loop( Chuck_Env * env, a_Stmt_Loop stmt ); t_CKBOOL type_engine_check_break( Chuck_Env * env, a_Stmt_Break br ); t_CKBOOL type_engine_check_continue( Chuck_Env * env, a_Stmt_Continue cont ); t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt ); t_CKBOOL type_engine_check_switch( Chuck_Env * env, a_Stmt_Switch stmt ); t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp ); t_CKTYPE type_engine_check_exp_binary( Chuck_Env * env, a_Exp_Binary binary ); t_CKTYPE type_engine_check_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKTYPE type_engine_check_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ); t_CKTYPE type_engine_check_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKTYPE type_engine_check_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ); t_CKTYPE type_engine_check_exp_unary( Chuck_Env * env, a_Exp_Unary unary ); t_CKTYPE type_engine_check_exp_primary( Chuck_Env * env, a_Exp_Primary exp ); t_CKTYPE type_engine_check_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ); t_CKTYPE type_engine_check_exp_cast( Chuck_Env * env, a_Exp_Cast cast ); t_CKTYPE type_engine_check_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ); t_CKTYPE type_engine_check_exp_dur( Chuck_Env * env, a_Exp_Dur dur ); t_CKTYPE type_engine_check_exp_array( Chuck_Env * env, a_Exp_Array array ); t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ); t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ); t_CKTYPE type_engine_check_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ); t_CKTYPE type_engine_check_exp_if( Chuck_Env * env, a_Exp_If exp_if ); t_CKTYPE type_engine_check_exp_decl( Chuck_Env * env, a_Exp_Decl decl ); t_CKBOOL type_engine_check_array_subscripts( Chuck_Env * env, a_Exp exp_list ); t_CKBOOL type_engine_check_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ); t_CKBOOL type_engine_check_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push = TRUE ); t_CKBOOL type_engine_check_func_def( Chuck_Env * env, a_Func_Def func_def ); t_CKBOOL type_engine_check_class_def( Chuck_Env * env, a_Class_Def class_def ); // helper a_Func_Def make_dll_as_fun( Chuck_DL_Func * dl_fun, t_CKBOOL is_static ); // static Chuck_Env * Chuck_Env::our_instance = NULL; //----------------------------------------------------------------------------- // name: startup() // desc: //----------------------------------------------------------------------------- t_CKBOOL Chuck_Env::startup() { assert( our_instance == NULL ); our_instance = new Chuck_Env; assert( our_instance != NULL ); return TRUE; } //----------------------------------------------------------------------------- // name: instance() // desc: ... //----------------------------------------------------------------------------- Chuck_Env * Chuck_Env::instance() { return our_instance; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_Env::shutdown() { assert( our_instance != NULL ); SAFE_DELETE( our_instance ); assert( our_instance == NULL ); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_init() // desc: initialize a type engine //----------------------------------------------------------------------------- Chuck_Env * type_engine_init( Chuck_VM * vm ) { // log EM_log( CK_LOG_SEVERE, "initializing type checker..." ); // push indent level EM_pushlog(); // allocate a new env if( !Chuck_Env::startup() ) return NULL; // get the instance Chuck_Env * env = Chuck_Env::instance(); // set the name of global namespace env->global()->name = "global"; // set the current namespace to global env->curr = env->global(); // enter the default global type mapping : lock VM objects to catch deletion env->global()->type.add( t_void.name, &t_void ); t_void.lock(); env->global()->type.add( t_int.name, &t_int ); t_int.lock(); env->global()->type.add( t_float.name, &t_float ); t_float.lock(); env->global()->type.add( t_time.name, &t_time ); t_time.lock(); env->global()->type.add( t_dur.name, &t_dur ); t_dur.lock(); env->global()->type.add( t_object.name, &t_object ); t_object.lock(); env->global()->type.add( t_string.name, &t_string ); t_string.lock(); env->global()->type.add( t_ugen.name, &t_ugen ); t_ugen.lock(); env->global()->type.add( t_shred.name, &t_shred ); t_shred.lock(); env->global()->type.add( t_thread.name, &t_thread ); t_thread.lock(); env->global()->type.add( t_function.name, &t_function ); t_function.lock(); env->global()->type.add( t_class.name, &t_class ); t_class.lock(); env->global()->type.add( t_array.name, &t_array ); t_array.lock(); env->global()->type.add( t_event.name, &t_event ); t_event.lock(); // dur value t_CKDUR samp = 1.0; // TODO: t_CKDUR second = vm->srate() * samp; // t_CKDUR second = 44100 * samp; t_CKDUR ms = second / 1000.0; t_CKDUR minute = second * 60.0; t_CKDUR hour = minute * 60.0; t_CKDUR day = hour * 24.0; t_CKDUR week = day * 7.0; // add internal classes EM_log( CK_LOG_SEVERE, "adding base classes..." ); EM_pushlog(); init_class_object( env, &t_object ); init_class_array( env, &t_array ); init_class_string( env, &t_string ); init_class_ugen( env, &t_ugen ); init_class_shred( env, &t_shred ); init_class_event( env, &t_event ); EM_log( CK_LOG_SEVERE, "class 'class'" ); t_class.info = new Chuck_Namespace; t_class.info->add_ref(); t_thread.info = new Chuck_Namespace; t_thread.info->add_ref(); // pop indent EM_poplog(); // default global values env->global()->value.add( "null", new Chuck_Value( &t_null, "null", new void *(NULL), TRUE ) ); env->global()->value.add( "NULL", new Chuck_Value( &t_null, "NULL", new void *(NULL), TRUE ) ); env->global()->value.add( "t_zero", new Chuck_Value( &t_time, "time_zero", new t_CKDUR(0.0), TRUE ) ); env->global()->value.add( "d_zero", new Chuck_Value( &t_dur, "dur_zero", new t_CKDUR(0.0), TRUE ) ); env->global()->value.add( "samp", new Chuck_Value( &t_dur, "samp", new t_CKDUR(samp), TRUE ) ); env->global()->value.add( "ms", new Chuck_Value( &t_dur, "ms", new t_CKDUR(ms), TRUE ) ); env->global()->value.add( "second", new Chuck_Value( &t_dur, "second", new t_CKDUR(second), TRUE ) ); env->global()->value.add( "minute", new Chuck_Value( &t_dur, "minute", new t_CKDUR(minute), TRUE ) ); env->global()->value.add( "hour", new Chuck_Value( &t_dur, "hour", new t_CKDUR(hour), TRUE ) ); env->global()->value.add( "day", new Chuck_Value( &t_dur, "day", new t_CKDUR(day), TRUE ) ); env->global()->value.add( "week", new Chuck_Value( &t_dur, "week", new t_CKDUR(week), TRUE ) ); env->global()->value.add( "true", new Chuck_Value( &t_int, "true", new t_CKINT(1), TRUE ) ); env->global()->value.add( "false", new Chuck_Value( &t_int, "false", new t_CKINT(0), TRUE ) ); env->global()->value.add( "maybe", new Chuck_Value( &t_int, "maybe", new t_CKFLOAT(.5), FALSE ) ); env->global()->value.add( "pi", new Chuck_Value( &t_float, "pi", new t_CKFLOAT(ONE_PI), TRUE ) ); env->global()->value.add( "global", new Chuck_Value( &t_class, "global", env->global(), TRUE ) ); // TODO: can't use the following now is local to shred // env->global()->value.add( "now", new Chuck_Value( &t_time, "now", &(vm->shreduler()->now_system), TRUE ) ); /* S_enter( e->value, insert_symbol( "machine" ), &t_null ); S_enter( e->value, insert_symbol( "language" ), &t_null ); S_enter( e->value, insert_symbol( "compiler" ), &t_null ); S_enter( e->value, insert_symbol( "chout" ), &t_system_out ); S_enter( e->value, insert_symbol( "cherr" ), &t_system_err ); S_enter( e->value, insert_symbol( "stdout" ), &t_system_out ); S_enter( e->value, insert_symbol( "stderr" ), &t_system_err ); S_enter( e->value, insert_symbol( "midiout" ), &t_midiout ); S_enter( e->value, insert_symbol( "midiin" ), &t_midiin ); S_enter( e->value, insert_symbol( "adc" ), &t_adc ); S_enter( e->value, insert_symbol( "dac" ), &t_dac ); S_enter( e->value, insert_symbol( "bunghole" ), &t_bunghole ); S_enter( e->value, insert_symbol( "blackhole" ), &t_bunghole ); S_enter( e->value, insert_symbol( "endl" ), &t_string ); */ // add reserve words env->key_words["for"] = TRUE; env->key_words["while"] = TRUE; env->key_words["until"] = TRUE; env->key_words["if"] = TRUE; env->key_words["else"] = TRUE; env->key_words["spork"] = TRUE; env->key_words["return"] = TRUE; env->key_words["class"] = TRUE; env->key_words["extends"] = TRUE; env->key_words["implements"] = TRUE; env->key_words["function"] = TRUE; env->key_words["fun"] = TRUE; env->key_words["public"] = TRUE; env->key_words["protected"] = TRUE; env->key_words["private"] = TRUE; env->key_words["static"] = TRUE; env->key_words["pure"] = TRUE; env->key_words["function"] = TRUE; env->key_words["fun"] = TRUE; env->key_words["break"] = TRUE; env->key_words["continue"] = TRUE; env->key_values["now"] = TRUE; env->key_values["true"] = TRUE; env->key_values["false"] = TRUE; env->key_values["maybe"] = TRUE; env->key_values["pi"] = TRUE; env->key_values["this"] = TRUE; env->key_values["super"] = TRUE; env->key_values["me"] = TRUE; env->key_values["samp"] = TRUE; env->key_values["ms"] = TRUE; env->key_values["second"] = TRUE; env->key_values["minute"] = TRUE; env->key_values["hour"] = TRUE; env->key_values["day"] = TRUE; env->key_values["week"] = TRUE; env->key_values["adc"] = TRUE; env->key_values["dac"] = TRUE; env->key_values["blackhole"] = TRUE; env->key_values["global"] = TRUE; env->key_values["null"] = TRUE; env->key_values["NULL"] = TRUE; env->key_types["void"] = TRUE; env->key_types["same"] = TRUE; env->key_types["int"] = TRUE; env->key_types["float"] = TRUE; // env->key_types["dur"] = TRUE; // env->key_types["time"] = TRUE; // env->key_types["Object"] = TRUE; // env->key_types["string"] = TRUE; // env->key_types["Shred"] = TRUE; // env->key_types["Event"] = TRUE; // env->key_types["UGen"] = TRUE; // env->key_types["machine"] = TRUE; // env->key_types["language"] = TRUE; // env->key_types["compiler"] = TRUE; // commit the global namespace env->global()->commit(); // pop indent level EM_poplog(); return env; } //----------------------------------------------------------------------------- // name: type_engine_shutdown() // desc: ... //----------------------------------------------------------------------------- void type_engine_shutdown( Chuck_Env * env ) { // log EM_log( CK_LOG_SEVERE, "shutting down type checker..." ); // shut it down Chuck_Env::shutdown(); // TODO: free these properly SAFE_RELEASE( t_object.info ); SAFE_RELEASE( t_array.info ); SAFE_RELEASE( t_string.info ); SAFE_RELEASE( t_ugen.info ); SAFE_RELEASE( t_shred.info ); SAFE_RELEASE( t_event.info ); SAFE_RELEASE( t_class.info ); SAFE_RELEASE( t_thread.info ); } //----------------------------------------------------------------------------- // name: type_engine_check_prog() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_prog( Chuck_Env * env, a_Program prog, const string & filename ) { t_CKBOOL ret = FALSE; // log EM_log( CK_LOG_FINE, "type-checking program '%s' - passes 0, 1, 2, 3...", filename.c_str() ); // push indent EM_pushlog(); // make the context Chuck_Context * context = type_engine_make_context( prog, filename ); if( !context ) goto done; // reset the env env->reset(); // load the context if( !type_engine_load_context( env, context ) ) { ret = FALSE; goto done; } // 0th-scan (pass 0) if( !type_engine_scan0_prog( env, g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 1st-scan (pass 1) if( !type_engine_scan1_prog( env, g_program, te_do_all ) ) { ret = FALSE; goto cleanup; } // 2nd-scan (pass 2) if( !type_engine_scan2_prog( env, prog, te_do_all ) ) { ret = FALSE; goto cleanup; } // check the context (pass 3) if( !type_engine_check_context( env, context ) ) { ret = FALSE; goto cleanup; } cleanup: // commit if( ret ) env->global()->commit(); // or rollback else env->global()->rollback(); // unload the context from the type-checker if( !type_engine_unload_context( env ) ) { EM_error2( 0, "internal error unloading context...\n" ); ret = FALSE; } done: // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_make_context() // desc: ... //----------------------------------------------------------------------------- Chuck_Context * type_engine_make_context( a_Program prog, const string & filename ) { // log EM_log( CK_LOG_FINER, "creating context '%s'...", filename.c_str() ); // push indent EM_pushlog(); // each parse tree corresponds to a chuck context Chuck_Context * context = new Chuck_Context; // save a reference to the parse tree context->parse_tree = prog; // set name context->filename = filename; // pop indent EM_poplog(); return context; } //----------------------------------------------------------------------------- // name: type_engine_check_context() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_context( Chuck_Env * env, Chuck_Context * context, te_HowMuch how_much ) { t_CKBOOL ret = TRUE; a_Program prog = NULL; // log EM_log( CK_LOG_FINER, "(pass 3) type-checking context '%s'...", context->filename.c_str() ); // push indent EM_pushlog(); // how much EM_log( CK_LOG_FINER, "target: %s", howmuch2str( how_much ) ); // make sure there is a context if( !env->context ) { // error EM_error2( 0, "internal error: env->context NULL!" ); ret = FALSE; goto done; } // parse tree prog = context->parse_tree; if( !prog ) { // error EM_error2( 0, "internal error: context->parse_tree NULL!" ); ret = FALSE; goto done; } // go through each of the program sections while( prog && ret ) { switch( prog->section->s_type ) { case ae_section_stmt: // if only classes, then skip if( how_much == te_do_classes_only ) break; // check the statements ret = type_engine_check_stmt_list( env, prog->section->stmt_list ); break; case ae_section_func: // if only classes, then skip if( how_much == te_do_classes_only ) break; // check the function definition ret = type_engine_check_func_def( env, prog->section->func_def ); break; case ae_section_class: // if no classes, then skip if( how_much == te_do_no_classes ) break; // check the class definition ret = type_engine_check_class_def( env, prog->section->class_def ); break; default: EM_error2( prog->linepos, "internal error: unrecognized program section in type checker..." ); ret = FALSE; break; } prog = prog->next; } // make sure we still have the same context assert( env->contexts.size() != 0 ); // assert( env->contexts.back() == context ); // check to see if everything passed if( !ret ) { // TODO: remove the effects of the context in the env // ---> insert code here <---- // flag the context with error, so more stuff gets deleted env->context->has_error = TRUE; } done: // pop indent EM_poplog(); return ret; } //----------------------------------------------------------------------------- // name: type_engine_load_context() // desc: call this before context is type-checked //----------------------------------------------------------------------------- t_CKBOOL type_engine_load_context( Chuck_Env * env, Chuck_Context * context ) { // log EM_log( CK_LOG_FINER, "loading context '%s'...", context->filename.c_str() ); // push indent EM_pushlog(); if( env->context ) EM_log( CK_LOG_FINER, "pushing existing context '%s'...", env->context->filename.c_str() ); // append the context to the env env->contexts.push_back( env->context ); // make the context current env->context = context; // add reference env->context->add_ref(); // push the context scope env->context->nspc->value.push(); // push the current namespaces env->nspc_stack.push_back( env->curr ); // set the parent context->nspc->parent = env->curr; // set the context's namespace as current env->curr = context->nspc; // pop indent EM_poplog(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_unload_context() // desc: call this after context is emitted //----------------------------------------------------------------------------- t_CKBOOL type_engine_unload_context( Chuck_Env * env ) { // make sure assert( env->context != NULL ); assert( env->contexts.size() != 0 ); // log EM_log( CK_LOG_FINER, "unloading context '%s'...", env->context->filename.c_str() ); // push indent EM_pushlog(); EM_log( CK_LOG_FINER, "restoring context '%s'...", env->contexts.back()->filename.c_str() ); // assert( env->context->has_error == FALSE ); // pop the context scope env->context->nspc->value.pop(); // restore the current namespace env->curr = env->nspc_stack.back(); // pop the namespace stack env->nspc_stack.pop_back(); // release the context env->context->release(); // restore context env->context = env->contexts.back(); // pop the context env->contexts.pop_back(); // make sure the nspc is ok assert( env->nspc_stack.size() != 0 ); // assert( env->stack.back() == &(context->nspc) ); // pop indent EM_poplog(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_stmt_list() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_stmt_list( Chuck_Env * env, a_Stmt_List list ) { // type check the stmt_list while( list ) { // the current statement if( !type_engine_check_stmt( env, list->stmt ) ) return FALSE; // advance to the next statement list = list->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_stmt(() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt ) { t_CKBOOL ret = FALSE; if( !stmt ) return TRUE; // the type of stmt switch( stmt->s_type ) { case ae_stmt_if: // count scope to help determine class member env->class_scope++; env->curr->value.push(); ret = type_engine_check_if( env, &stmt->stmt_if ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_for: env->class_scope++; env->curr->value.push(); ret = type_engine_check_for( env, &stmt->stmt_for ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_while: env->class_scope++; env->curr->value.push(); ret = type_engine_check_while( env, &stmt->stmt_while ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_until: env->class_scope++; env->curr->value.push(); ret = type_engine_check_until( env, &stmt->stmt_until ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_loop: env->class_scope++; env->curr->value.push(); ret = type_engine_check_loop( env, &stmt->stmt_loop ); env->curr->value.pop(); env->class_scope--; break; case ae_stmt_exp: ret = ( type_engine_check_exp( env, stmt->stmt_exp ) != NULL ); break; case ae_stmt_return: ret = type_engine_check_return( env, &stmt->stmt_return ); break; case ae_stmt_code: env->class_scope++; ret = type_engine_check_code_segment( env, &stmt->stmt_code ); env->class_scope--; break; case ae_stmt_break: ret = type_engine_check_break( env, &stmt->stmt_break ); break; case ae_stmt_continue: ret = type_engine_check_continue( env, &stmt->stmt_continue ); break; case ae_stmt_switch: env->class_scope++; ret = type_engine_check_switch( env, &stmt->stmt_switch ); env->class_scope--; break; case ae_stmt_case: // ret = type_engine_check_case( env, &stmt->stmt_case ); break; case ae_stmt_gotolabel: // ret = type_engine_check_gotolabel( env, &stmt->goto_label ); break; default: EM_error2( stmt->linepos, "internal compiler error - no stmt type '%i'!", stmt->s_type ); ret = FALSE; break; } return ret; } //----------------------------------------------------------------------------- // name: type_engine_check_if() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_if( Chuck_Env * env, a_Stmt_If stmt ) { // check the conditional if( !type_engine_check_exp( env, stmt->cond ) ) return FALSE; // TODO: ensure that conditional has valid type // check if if( !type_engine_check_stmt( env, stmt->if_body ) ) return FALSE; // check else, if there is one if( stmt->else_body ) if( !type_engine_check_stmt( env, stmt->else_body ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_for() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_for( Chuck_Env * env, a_Stmt_For stmt ) { // check the initial if( !type_engine_check_stmt( env, stmt->c1 ) ) return FALSE; // check the conditional if( !type_engine_check_stmt( env, stmt->c2 ) ) return FALSE; // TODO: same as if - check conditional type valid // check the post if( stmt->c3 && !type_engine_check_exp( env, stmt->c3 ) ) return FALSE; // for break and continue statement env->breaks.push_back( stmt->self ); // check body // TODO: restore break stack? (same for other loops) if( !type_engine_check_stmt( env, stmt->body ) ) return FALSE; // remove the loop from the stack assert( env->breaks.size() && env->breaks.back() == stmt->self ); env->breaks.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_while() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_while( Chuck_Env * env, a_Stmt_While stmt ) { // check the conditional if( !type_engine_check_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // for break and continue statement env->breaks.push_back( stmt->self ); // check the body if( !type_engine_check_stmt( env, stmt->body ) ) return FALSE; // remove the loop from the stack assert( env->breaks.size() && env->breaks.back() == stmt->self ); env->breaks.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_until() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_until( Chuck_Env * env, a_Stmt_Until stmt ) { // check the conditional if( !type_engine_check_exp( env, stmt->cond ) ) return FALSE; // TODO: same as if - ensure the type in conditional is valid // for break and continue statement env->breaks.push_back( stmt->self ); // check the body if( !type_engine_check_stmt( env, stmt->body ) ) return FALSE; // remove the loop from the stack assert( env->breaks.size() && env->breaks.back() == stmt->self ); env->breaks.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_loop() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_loop( Chuck_Env * env, a_Stmt_Loop stmt ) { Chuck_Type * type = NULL; // check the conditional if( !(type = type_engine_check_exp( env, stmt->cond )) ) return FALSE; // ensure the type in conditional is int (different from other loops) if( isa( type, &t_float ) ) { // cast stmt->cond->cast_to = &t_int; } else if( !isa( type, &t_int ) ) // must be int { EM_error2( stmt->linepos, "loop * conditional must be of type 'int'..." ); return FALSE; } // for break and continue statement env->breaks.push_back( stmt->self ); // check the body if( !type_engine_check_stmt( env, stmt->body ) ) return FALSE; // remove the loop from the stack assert( env->breaks.size() && env->breaks.back() == stmt->self ); env->breaks.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_switch() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_switch( Chuck_Env * env, a_Stmt_Switch stmt ) { // TODO: implement this EM_error2( stmt->linepos, "switch not implemented..." ); return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_check_break() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_break( Chuck_Env * env, a_Stmt_Break br ) { // check to see if inside valid stmt if( env->breaks.size() <= 0 ) { EM_error2( br->linepos, "'break' found outside of for/while/until/switch..." ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_continue() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_continue( Chuck_Env * env, a_Stmt_Continue cont ) { // check to see if inside valid loop if( env->breaks.size() <= 0 ) { EM_error2( cont->linepos, "'continue' found outside of for/while/until..." ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_return() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_return( Chuck_Env * env, a_Stmt_Return stmt ) { Chuck_Type * ret_type = NULL; // check to see if within function definition if( !env->func ) { EM_error2( stmt->linepos, "'return' statement found outside function definition" ); return FALSE; } // check the type of the return if( stmt->val ) ret_type = type_engine_check_exp( env, stmt->val ); else ret_type = &t_void; // check to see that return type matches the prototype if( ret_type && !isa( ret_type, env->func->def->ret_type ) ) { EM_error2( stmt->linepos, "function '%s' was defined with return type '%s' -- but returning type '%s'", env->func->name.c_str(), env->func->def->ret_type->c_name(), ret_type->c_name() ); return FALSE; } return ret_type != NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_code_segment() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_code_segment( Chuck_Env * env, a_Stmt_Code stmt, t_CKBOOL push ) { // TODO: make sure this is in a function or is outside class // class env->class_scope++; // push if( push ) env->curr->value.push(); // env->context->nspc.value.push(); // do it t_CKBOOL t = type_engine_check_stmt_list( env, stmt->stmt_list ); // pop if( push ) env->curr->value.pop(); // env->context->nspc.value.pop(); // class env->class_scope--; return t; } //----------------------------------------------------------------------------- // name: type_engine_check_exp() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp ) { a_Exp curr = exp; // reset the group size exp->group_size = 0; // loop through parallel expressions while( curr ) { // reset the type curr->type = NULL; // increment first exp's group size exp->group_size++; // examine the syntax switch( curr->s_type ) { case ae_exp_binary: curr->type = type_engine_check_exp_binary( env, &curr->binary ); break; case ae_exp_unary: curr->type = type_engine_check_exp_unary( env, &curr->unary ); break; case ae_exp_cast: curr->type = type_engine_check_exp_cast( env, &curr->cast ); break; case ae_exp_postfix: curr->type = type_engine_check_exp_postfix( env, &curr->postfix ); break; case ae_exp_dur: curr->type = type_engine_check_exp_dur( env, &curr->dur ); break; case ae_exp_primary: curr->type = type_engine_check_exp_primary( env, &curr->primary ); break; case ae_exp_array: curr->type = type_engine_check_exp_array( env, &curr->array ); break; case ae_exp_func_call: curr->type = type_engine_check_exp_func_call( env, &curr->func_call ); // set the return type curr->func_call.ret_type = curr->type; break; case ae_exp_dot_member: curr->type = type_engine_check_exp_dot_member( env, &curr->dot_member ); break; case ae_exp_if: curr->type = type_engine_check_exp_if( env, &curr->exp_if ); break; case ae_exp_decl: curr->type = type_engine_check_exp_decl( env, &curr->decl ); break; default: EM_error2( curr->linepos, "internal compiler error - no expression type '%i'...", curr->s_type ); return NULL; } // error if( !curr->type ) return NULL; // advance to next expression curr = curr->next; } // return type return exp->type; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_binary() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_binary( Chuck_Env * env, a_Exp_Binary binary ) { a_Exp cl = binary->lhs, cr = binary->rhs; t_CKTYPE ret = NULL; // type check the lhs and rhs t_CKTYPE left = type_engine_check_exp( env, cl ); t_CKTYPE right = type_engine_check_exp( env, cr ); // if either fails, then return NULL if( !left || !right ) return NULL; // cross chuck while( cr ) { // type check the pair if( !(ret = type_engine_check_op( env, binary->op, cl, cr, binary )) ) return NULL; cr = cr->next; } return ret; } //----------------------------------------------------------------------------- // name: type_engine_ensure_no_multi_decl() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_ensure_no_multi_decl( a_Exp exp, const char * op_str ) { // go if( exp->s_type == ae_exp_decl && exp->decl.num_var_decls > 1 ) { // multiple declarations on left side EM_error2( exp->linepos, "cannot '%s' from/to a multi-variable declaration", op_str ); return FALSE; } return TRUE; } // helper macros #define LR( L, R ) if( (left->xid == L) && (right->xid == R) ) #define COMMUTE( L, R ) if( ( (left->xid == L) && (right->xid == R) ) || \ ( (left->xid == R) && (right->xid == L) ) ) //----------------------------------------------------------------------------- // name: type_engine_check_op() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_op( Chuck_Env * env, ae_Operator op, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { t_CKTYPE left = lhs->type, right = rhs->type; assert( left && right ); // make sure not involve multiple declarations (for now) if( !type_engine_ensure_no_multi_decl( lhs, op2str(op) ) || !type_engine_ensure_no_multi_decl( rhs, op2str(op) ) ) return FALSE; // if lhs is multi-value, then check separately if( (lhs->next && op != ae_op_chuck /*&& !isa( right, &t_function)*/ ) || rhs->next ) { // TODO: implement this EM_error2( lhs->linepos, "multi-value (%s) operation not supported/implemented...", op2str(op)); return NULL; } // implicit cast if( *left != *right ) { // for some - int/float switch( op ) { case ae_op_plus: case ae_op_minus: case ae_op_times: case ae_op_divide: case ae_op_lt: case ae_op_le: case ae_op_gt: case ae_op_ge: case ae_op_eq: case ae_op_neq: case ae_op_percent: // mark for cast LR( te_int, te_float ) left = lhs->cast_to = &t_float; else LR( te_float, te_int ) right = rhs->cast_to = &t_float; break; default: break; } // no commute - int/float switch( op ) { case ae_op_plus_chuck: case ae_op_minus_chuck: case ae_op_times_chuck: case ae_op_divide_chuck: case ae_op_percent_chuck: // mark for cast LR( te_int, te_float ) left = lhs->cast_to = &t_float; break; default: break; } // int/dur if( op == ae_op_times ) { LR( te_int, te_dur ) left = lhs->cast_to = &t_float; else LR( te_dur, te_int ) right = rhs->cast_to = &t_float; } else if( op == ae_op_divide ) { LR( te_dur, te_int ) right = rhs->cast_to = &t_float; } } // objects switch( op ) { case ae_op_plus: case ae_op_plus_chuck: // take care of string if( isa( left, &t_string ) ) { // right is string or int/float if( isa( right, &t_string ) || isa( right, &t_int ) || isa( right, &t_float ) ) break; } else if( isa( left, &t_string ) || isa( left, &t_int ) || isa( left, &t_float ) ) { // right is string if( isa( right, &t_string ) ) break; } case ae_op_minus: case ae_op_times: case ae_op_divide: //case ae_op_lt: //case ae_op_le: //case ae_op_gt: //case ae_op_ge: case ae_op_percent: case ae_op_minus_chuck: case ae_op_times_chuck: case ae_op_divide_chuck: case ae_op_percent_chuck: if( isa( left, &t_object ) ) { EM_error2( lhs->linepos, "cannot perform '%s' on object references...", op2str(op) ); return NULL; } if( isa( right, &t_object ) ) { EM_error2( lhs->linepos, "cannot perform '%s' on object references...", op2str(op) ); return NULL; } break; default: break; } // make sure switch( op ) { case ae_op_plus_chuck: case ae_op_minus_chuck: case ae_op_times_chuck: case ae_op_divide_chuck: case ae_op_percent_chuck: case ae_op_s_and_chuck: case ae_op_s_or_chuck: case ae_op_s_xor_chuck: case ae_op_shift_left_chuck: case ae_op_shift_right_chuck: // make sure mutable if( rhs->s_meta != ae_meta_var ) { EM_error2( lhs->linepos, "cannot assign '%s' on types '%s' %s '%s'...", op2str( op ), left->c_name(), op2str( op ), right->c_name() ); EM_error2( lhs->linepos, "...(reason: --- right-side operand is not mutable)" ); return NULL; } // mark to emit var instead of value rhs->emit_var = 1; break; default: break; } // based on the op switch( op ) { case ae_op_chuck: return type_engine_check_op_chuck( env, lhs, rhs, binary ); case ae_op_unchuck: return type_engine_check_op_unchuck( env, lhs, rhs ); case ae_op_at_chuck: return type_engine_check_op_at_chuck( env, lhs, rhs ); case ae_op_plus_chuck: if( isa( left, &t_string ) && isa( right, &t_string ) ) return &t_string; if( isa( left, &t_int ) && isa( right, &t_string ) ) return &t_string; if( isa( left, &t_float ) && isa( right, &t_string ) ) return &t_string; case ae_op_plus: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; LR( te_dur, te_dur ) return &t_dur; COMMUTE( te_dur, te_time ) return &t_time; if( isa( left, &t_string ) && isa( right, &t_string ) ) return &t_string; if( isa( left, &t_string ) && isa( right, &t_int ) ) return &t_string; if( isa( left, &t_string ) && isa( right, &t_float ) ) return &t_string; if( isa( left, &t_int ) && isa( right, &t_string ) ) return &t_string; if( isa( left, &t_float ) && isa( right, &t_string ) ) return &t_string; break; case ae_op_minus: LR( te_time, te_time ) return &t_dur; LR( te_time, te_dur ) return &t_time; LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; LR( te_dur, te_dur ) return &t_dur; break; // take care of non-commutative case ae_op_minus_chuck: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; LR( te_dur, te_dur ) return &t_dur; LR( te_dur, te_time ) return &t_time; break; case ae_op_times_chuck: case ae_op_times: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; COMMUTE( te_float, te_dur ) return &t_dur; break; case ae_op_divide: LR( te_dur, te_dur ) return &t_float; LR( te_time, te_dur ) return &t_float; LR( te_dur, te_float ) return &t_dur; LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; break; // take care of non-commutative case ae_op_divide_chuck: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; LR( te_float, te_dur ) return &t_dur; break; case ae_op_eq: // null // if( isa( left, &t_object ) && isa( right, &t_null ) ) return &t_int; // if( isa( left, &t_null ) && isa( right, &t_object ) ) return &t_int; case ae_op_lt: case ae_op_gt: case ae_op_le: case ae_op_ge: case ae_op_neq: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_int; LR( te_dur, te_dur ) return &t_int; LR( te_time, te_time ) return &t_int; if( isa( left, &t_object ) && isa( right, &t_object ) ) return &t_int; break; case ae_op_s_and_chuck: case ae_op_s_or_chuck: case ae_op_s_xor_chuck: case ae_op_shift_right_chuck: case ae_op_shift_left_chuck: // the above are non-commutative case ae_op_and: case ae_op_or: case ae_op_s_xor: case ae_op_s_and: case ae_op_s_or: case ae_op_shift_left: case ae_op_shift_right: LR( te_int, te_int ) return &t_int; break; case ae_op_percent: LR( te_time, te_dur ) return &t_dur; LR( te_dur, te_dur ) return &t_dur; LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; break; // take of non-commutative case ae_op_percent_chuck: LR( te_int, te_int ) return &t_int; LR( te_float, te_float ) return &t_float; LR( te_dur, te_dur ) return &t_dur; break; default: break; } // no match EM_error2( lhs->linepos, "cannot resolve operator '%s' on types '%s' and '%s'", op2str( op ), left->c_name(), right->c_name() ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_op_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_op_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs, a_Exp_Binary binary ) { t_CKTYPE left = lhs->type, right = rhs->type; // chuck to function if( isa( right, &t_function ) ) { // treat this function call return type_engine_check_exp_func_call( env, rhs, lhs, binary->ck_func, binary->linepos ); } // multi-value not supported beyond this for now if( lhs->next || rhs->next ) { EM_error2( lhs->linepos, "multi-value (=>) operation not supported/implemented..." ); return NULL; } // ugen => ugen if( isa( left, &t_ugen ) && isa( right, &t_ugen ) ) { // make sure non-zero if( left->ugen_info->num_outs == 0 ) { // error EM_error2( lhs->linepos, "ugen's of type '%s' have no output - cannot => to another ugen...", left->c_name() ); return NULL; } else if( right->ugen_info->num_ins == 0 ) { // error EM_error2( rhs->linepos, "ugen's of type '%s' have no input - cannot => from another ugen...", right->c_name() ); return NULL; } return right; } // time advance ( dur => now ) if( isa( left, &t_dur ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var && rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) { return right; } // event wait ( Event => now ) if( isa( left, &t_event ) && isa( right, &t_time ) && rhs->s_meta == ae_meta_var && rhs->s_type == ae_exp_primary && !strcmp( "now", S_name(rhs->primary.var) ) ) { return right; } // implicit cast LR( te_int, te_float ) left = lhs->cast_to = &t_float; // assignment or something else if( isa( left, right ) ) { // basic types? if( type_engine_check_primitive( left ) || isa( left, &t_string ) ) { // if the right is a decl, then make sure ref if( isa( left, &t_string ) && rhs->s_type == ae_exp_decl ) { rhs->decl.type->ref = TRUE; } // TODO: const // assigment? if( rhs->s_meta == ae_meta_var ) { // emit ref - remember for emitter rhs->emit_var = TRUE; // right side return right; } // error EM_error2( lhs->linepos, "cannot chuck/assign '=>' on types '%s' => '%s'...", left->c_name(), right->c_name() ); EM_error2( lhs->linepos, "...(reason: right-side operand is not mutable)" ); return NULL; } // aggregate types else { // TODO: check overloading of => // no match EM_error2( lhs->linepos, "cannot resolve operator '=>' on types '%s' and '%s'...", left->c_name(), right->c_name() ); EM_error2( lhs->linepos, "...(note: use '@=>' for object reference assignment)" ); return NULL; } } // TODO: check overloading of => // no match EM_error2( lhs->linepos, "cannot resolve operator '=>' on types '%s' and '%s'...", left->c_name(), right->c_name() ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_op_unchuck() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_op_unchuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { t_CKTYPE left = lhs->type, right = rhs->type; // ugen =< ugen if( isa( left, &t_ugen ) && isa( right, &t_ugen ) ) return right; // TODO: check overloading of =< // no match EM_error2( lhs->linepos, "no suitable resolution for binary operator '=<'..." ); EM_error2( lhs->linepos, "...on types '%s' and '%s'", left->c_name(), right->c_name() ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_op_at_chuck() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_op_at_chuck( Chuck_Env * env, a_Exp lhs, a_Exp rhs ) { t_CKTYPE left = lhs->type, right = rhs->type; // static //if( isa( left, &t_class ) ) //{ // EM_error2( lhs->linepos, // "cannot assign '@=>' using static class as left operand..." ); // return NULL; //} //else if( isa( right, &t_class ) ) //{ // EM_error2( rhs->linepos, // "cannot assign '@=>' using static class as right operand..." ); // return NULL; //} // make sure mutable if( rhs->s_meta != ae_meta_var ) { EM_error2( lhs->linepos, "cannot assign '@=>' on types '%s' @=> '%s'...", left->c_name(), right->c_name() ); EM_error2( lhs->linepos, "...(reason: --- right-side operand is not mutable)" ); return NULL; } // if the right is a decl, then make sure ref if( rhs->s_type == ae_exp_decl ) { rhs->decl.type->ref = TRUE; } // implicit cast LR( te_int, te_float ) left = lhs->cast_to = &t_float; // primitive if( !isa( left, right ) ) { EM_error2( lhs->linepos, "cannot assign '@=>' on types '%s' @=> '%s'...", left->c_name(), right->c_name() ); EM_error2( lhs->linepos, "...(reason: --- incompatible types for assignment)" ); return NULL; } // assign rhs->emit_var = TRUE; return right; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_unary() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_unary( Chuck_Env * env, a_Exp_Unary unary ) { Chuck_Type * t = NULL; // make sure if( unary->exp ) { // assert( unary->op == ae_op_new ); t = type_engine_check_exp( env, unary->exp ); if( !t ) return NULL; } // check the op switch( unary->op ) { case ae_op_plusplus: case ae_op_minusminus: // assignable? if( unary->exp->s_meta != ae_meta_var ) { EM_error2( unary->linepos, "prefix unary operator '%s' cannot " "be used on non-mutable data-types...", op2str( unary->op ) ); return NULL; } // assign unary->exp->emit_var = TRUE; // check type if( isa( t, &t_int ) || isa( t, &t_float ) ) return t; // TODO: check overloading break; case ae_op_minus: // float if( isa( t, &t_float ) ) return t; case ae_op_tilda: case ae_op_exclamation: // int if( isa( t, &t_int ) ) return t; break; case ae_op_spork: // spork shred if( unary->exp->s_type == ae_exp_func_call ) return &t_shred; else { EM_error2( unary->linepos, "only function calls can be sporked..." ); return NULL; } break; case ae_op_new: // look up the type // t = env->curr->lookup_type( unary->type->xid->xid, TRUE ); t = type_engine_find_type( env, unary->type->xid ); if( !t ) { EM_error2( unary->linepos, "... in 'new' expression ..." ); return NULL; } // [] if( unary->array ) { // verify there are no errors from the parser... if( !verify_array( unary->array ) ) return NULL; // if empty if( !unary->array->exp_list ) { EM_error2( unary->linepos, "cannot use empty [] with 'new'..." ); return NULL; } // type check the exp if( !type_engine_check_exp( env, unary->array->exp_list ) ) return NULL; // make sure types are of int if( !type_engine_check_array_subscripts( env, unary->array->exp_list ) ) return NULL; // create the new array type, replace t t = new_array_type( env, // the env &t_array, // the array base class, usually &t_array unary->array->depth, // the depth of the new type t, // the 'array_type' env->curr // the owner namespace ); // TODO: ref? } // make sure the type is not a primitive if( isa( t, &t_int ) || isa( t, &t_float ) || isa( t, &t_dur ) || isa( t, &t_time ) ) { EM_error2( unary->linepos, "cannot instantiate/(new) primitive type '%s'...", t->c_name() ); EM_error2( unary->linepos, "...(primitive types: 'int', 'float', 'time', 'dur')" ); return NULL; } // make sure the type is not a reference if( unary->type->ref && !unary->array ) { EM_error2( unary->linepos, "cannot instantiate/(new) single object references (@)..." ); return NULL; } // return the type return t; break; default: break; } // no match EM_error2( unary->linepos, "no suitable resolution for prefix unary operator '%s' on type '%s...", op2str( unary->op ), t->c_name() ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_primary() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_primary( Chuck_Env * env, a_Exp_Primary exp ) { t_CKTYPE t = NULL; Chuck_Value * v = NULL; string str; // check syntax switch( exp->s_type ) { // variable case ae_primary_var: str = S_name(exp->var); // check it if( str == "this" ) // this { // in class def if( !env->class_def ) { EM_error2( exp->linepos, "keyword 'this' can be used only inside class definition..." ); return NULL; } // in member func if( env->func && !env->func->is_member ) { EM_error2( exp->linepos, "keyword 'this' cannot be used inside static functions..." ); return NULL; } // not assignable exp->self->s_meta = ae_meta_value; // whatever the class is t = env->class_def; } else if( str == "me" ) // me { // not assignable exp->self->s_meta = ae_meta_value; // refers to shred t = &t_shred; } else if( str == "now" ) // now { // assignable in a strongly timed way exp->self->s_meta = ae_meta_var; // time t = &t_time; } else if( str == "dac" ) // dac { // not assignable exp->self->s_meta = ae_meta_value; // ugen t = g_t_dac; } else if( str == "adc" ) // adc { // not assignable exp->self->s_meta = ae_meta_value; // ugen t = g_t_adc; } else if( str == "blackhole" ) // blackhole { // non assignable exp->self->s_meta = ae_meta_value; // ugen t = &t_ugen; } else if( str == "null" || str == "NULL" ) // null / NULL { // not assignable exp->self->s_meta = ae_meta_value; // refers to null t = &t_null; } else // look up { // look in local scope first // v = env->curr->lookup_value( exp->var, FALSE ); v = type_engine_find_value( env, S_name(exp->var), FALSE ); if( !v ) { // if in class if( env->class_def ) { // see if in parent v = type_engine_find_value( env->class_def->parent, exp->var ); } // still not found if( !v ) { // look globally // v = env->curr->lookup_value( exp->var, TRUE ); v = type_engine_find_value( env, S_name(exp->var), TRUE, exp->linepos ); } // check if( v ) { // inside a class if( env->class_def ) { // inside a function definition if( env->func ) { // if func static, v not if( env->func->def->static_decl == ae_key_static && v->is_member && !v->is_static ) { EM_error2( exp->linepos, "non-static member '%s' used from static function...", S_name(exp->var) ); return NULL; } } } } // error else { // checking for class scope incorrect (thanks Robin Davies) if( !env->class_def /* || env->class_scope > 0 */ ) { EM_error2( exp->linepos, "undefined variable '%s'...", S_name(exp->var) ); return NULL; } else { EM_error2( exp->linepos, "undefined variable/member '%s' in class/namespace '%s'...", S_name(exp->var), env->class_def->name.c_str() ); return NULL; } } } // make sure v is legit as this point if( !v->is_decl_checked ) { EM_error2( exp->linepos, "variable/member '%s' is used before declaration...", S_name(exp->var) ); return NULL; } // the type t = v->type; // remember exp->value = v; } break; // int case ae_primary_num: t = &t_int; break; // float case ae_primary_float: t = &t_float; break; // string case ae_primary_str: // escape the thing if( !escape_str( exp->str, exp->linepos ) ) return NULL; // a string t = &t_string; break; // array literal case ae_primary_array: t = type_engine_check_exp_array_lit( env, exp ); break; // expression case ae_primary_exp: t = type_engine_check_exp( env, exp->exp ); break; // hack case ae_primary_hack: // make sure not l-value if( exp->exp->s_type == ae_exp_decl ) { EM_error2( exp->linepos, "cannot use <<< >>> on variable declarations..." ); return NULL; } t = type_engine_check_exp( env, exp->exp ); break; // nil case ae_primary_nil: t = &t_void; break; // no match default: EM_error2( exp->linepos, "internal error - unrecognized primary type '%i'...", exp->s_type ); return NULL; } return t; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_array_lit() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_array_lit( Chuck_Env * env, a_Exp_Primary exp ) { // make sure assert( exp->s_type == ae_primary_array ); // type Chuck_Type * t = NULL, * type = NULL, * common = NULL; // verify there are no errors from the parser... if( !verify_array( exp->array ) ) return NULL; // verify they are of same type - do this later? a_Exp e = exp->array->exp_list; // can't be [] if( !e ) { EM_error2( exp->linepos, "must provide values/expressions for array [...]" ); return NULL; } // go through the array and type check each if( !type_engine_check_exp( env, e ) ) return NULL; // loop while( e ) { // get the type t = e->type; // compare if( !type ) { // first type = t; } else { // find common ancestor common = type_engine_find_common_anc( t, type ); // update type if( common ) type = common; // no common else { // maybe one is int and other is float if( isa( t, &t_int ) && isa( type, &t_float ) ) { // cast from int to float e->cast_to = type; } else { // incompatible EM_error2( e->linepos, "array init [...] contains incompatible types..." ); return NULL; } } } // next exp e = e->next; } // make sure assert( type != NULL ); // treat static and dynamic separately // exp->array->is_dynamic = !is_static_array_lit( env, exp->array->exp_list ); // create the new array type t = new_array_type( env, // the env &t_array, // the array base class, usually &t_array type->array_depth + 1, // the depth of the new type type->array_depth ? type->array_type : type, // the 'array_type' env->curr // the owner namespace ); /* // create the new type t = env->context->new_Chuck_Type(); // set the xid t->xid = te_array; // set the name t->name = type->name; // set the parent t->parent = &t_array; // is a ref t->size = t_array.size; // set the array depth t->array_depth = type->array_depth + 1; // set the base type t->array_type = type->array_depth ? type->array_type : type; // TODO: verify the following is correct // set namespace t->info = t_array.info; // add reference t->info->add_ref(); // set owner t->owner = env->curr; */ return t; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_cast() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_cast( Chuck_Env * env, a_Exp_Cast cast ) { // check the exp t_CKTYPE t = type_engine_check_exp( env, cast->exp ); if( !t ) return NULL; // the type to cast to // t_CKTYPE t2 = env->curr->lookup_type( cast->type->xid->xid, TRUE ); t_CKTYPE t2 = type_engine_find_type( env, cast->type->xid ); if( !t2 ) { EM_error2( cast->linepos, "... in cast expression ..." ); return NULL; } // check if cast valid if( !type_engine_check_cast_valid( env, t2, t ) ) { EM_error2( cast->linepos, "invalid cast to '%s' from '%s'...", S_name( cast->type->xid->xid ), t->c_name() ); return NULL; } return t2; } //----------------------------------------------------------------------------- // name: type_engine_check_cast_valid() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_cast_valid( Chuck_Env * env, t_CKTYPE to, t_CKTYPE from ) { // down cast if( isa( from, to ) ) return TRUE; // up cast if( isa( to, from ) ) return TRUE; // TODO: dynamic type checking // int to float, float to int if( isa( to, &t_float ) && isa( from, &t_int ) ) return TRUE; if( isa( to, &t_int ) && isa( from, &t_float ) ) return TRUE; return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_dur() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_dur( Chuck_Env * env, a_Exp_Dur dur ) { // type check the two components t_CKTYPE base = type_engine_check_exp( env, dur->base ); t_CKTYPE unit = type_engine_check_exp( env, dur->unit ); // make sure both type check if( !base || !unit ) return NULL; // check base type if( !isa( base, &t_int ) && !isa( base, &t_float ) ) { EM_error2( dur->base->linepos, "invalid type '%s' in prefix of dur expression...\n" " (must be of type 'int' or 'float')", base->c_name() ); return NULL; } // check unit type if( !isa( unit, &t_dur ) ) { EM_error2( dur->unit->linepos, "invalid type '%s' in postfix of dur expression...\n" " (must be of type 'dur')", unit->c_name() ); return NULL; } return unit; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_postfix() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_postfix( Chuck_Env * env, a_Exp_Postfix postfix ) { // check the exp t_CKTYPE t = type_engine_check_exp( env, postfix->exp ); if( !t ) return NULL; // syntax switch( postfix->op ) { case ae_op_plusplus: case ae_op_minusminus: // assignable? if( postfix->exp->s_meta != ae_meta_var ) { EM_error2( postfix->exp->linepos, "postfix operator '%s' cannot be used on non-mutable data-type...", op2str( postfix->op ) ); return NULL; } postfix->exp->emit_var = TRUE; // TODO: mark somewhere we need to post increment // check type if( isa( t, &t_int ) || isa( t, &t_float ) ) return t; break; default: // no match EM_error2( postfix->linepos, "internal compiler error: unrecognized postfix '%i'", postfix->op ); return NULL; } // no match EM_error2( postfix->linepos, "no suitable resolutation for postfix operator '%s' on type '%s'...", op2str( postfix->op ), t->c_name() ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_if() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_if( Chuck_Env * env, a_Exp_If exp_if ) { // check the components t_CKTYPE cond = type_engine_check_exp( env, exp_if->cond ); t_CKTYPE if_exp = type_engine_check_exp( env, exp_if->if_exp ); t_CKTYPE else_exp = type_engine_check_exp( env, exp_if->else_exp ); // make sure everything good if( !cond || !if_exp || !else_exp ) return NULL; // check the type if( !isa( cond, &t_int ) ) return NULL; // make sure the if and else have compatible types // TODO: the lesser of two types if( !( *if_exp == *else_exp ) ) { EM_error2( exp_if->linepos, "incompatible types '%s' and '%s' in if expression...", if_exp->c_name(), else_exp->c_name() ); return NULL; } return if_exp; } //----------------------------------------------------------------------------- // name: type_engine_check_array_subscripts( ) // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_array_subscripts( Chuck_Env * env, a_Exp exp_list ) { a_Exp exp = exp_list; // loop through while( exp ) { // if not int if( !isa( exp->type, &t_int ) ) { EM_error2( exp->linepos, "incompatible array subscript type '%s'...", exp->type->name.c_str() ); return FALSE; } exp = exp->next; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_decl( ) // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_decl( Chuck_Env * env, a_Exp_Decl decl ) { a_Var_Decl_List list = decl->var_decl_list; a_Var_Decl var_decl = NULL; Chuck_Type * type = NULL; Chuck_Value * value = NULL; t_CKBOOL is_obj = FALSE; t_CKBOOL is_ref = FALSE; // loop through the variables while( list != NULL ) { // get the decl var_decl = list->var_decl; // (if at class_scope) check if in parent // TODO: sort if( env->class_def && env->class_scope == 0 && ( value = type_engine_find_value( env->class_def->parent, var_decl->xid ) ) ) { EM_error2( var_decl->linepos, "'%s' has already been defined in super class '%s'...", S_name(var_decl->xid), value->owner_class->c_name() ); return NULL; } // get the value value = var_decl->value; // make sure assert( value != NULL ); // get the type type = value->type; // make sure assert( type != NULL ); // is object is_obj = isobj( type ); // is ref is_ref = decl->type->ref; // if array, then check to see if empty [] if( var_decl->array && var_decl->array->exp_list != NULL ) { // instantiate object, including array if( !type_engine_check_exp( env, var_decl->array->exp_list ) ) return FALSE; // check the subscripts if( !type_engine_check_array_subscripts( env, var_decl->array->exp_list ) ) return FALSE; } // member? if( value->is_member ) { // offset value->offset = env->curr->offset; // move the offset (TODO: check the size) env->curr->offset += type->size; } else if( decl->is_static ) // static { // base scope if( env->class_def == NULL || env->class_scope > 0 ) { EM_error2( decl->linepos, "static variables must be declared at class scope..." ); return FALSE; } // flag value->is_static = TRUE; // offset value->offset = env->class_def->info->class_data_size; // move the size env->class_def->info->class_data_size += type->size; // if this is an object if( is_obj && !is_ref ) { // for now - no good for static, since we need separate // initialization which we don't have EM_error2( var_decl->linepos, "cannot declare static non-primitive objects (yet)..." ); EM_error2( var_decl->linepos, "...(hint: declare as ref (@) & initialize outside for now)" ); return FALSE; } } else // local variable { // do nothing? } // mark the decl checked (see scan pass 2) value->is_decl_checked = TRUE; // add the value, if we are not at class scope // (otherwise they should already have been added) if( !env->class_def || env->class_scope > 0 ) { // add as value env->curr->value.add( var_decl->xid, value ); } // the next var decl list = list->next; } return decl->ck_type; } //----------------------------------------------------------------------------- // name: type_engine_print_exp_dot_member() // desc: ... //----------------------------------------------------------------------------- string type_engine_print_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ) { // UNUSED: Chuck_Value * value = NULL; Chuck_Type * the_base = NULL; t_CKBOOL base_static = FALSE; string str; // type check the base member->t_base = type_engine_check_exp( env, member->base ); if( !member->t_base ) return "[error]"; // is the base a class/namespace or a variable base_static = isa( member->t_base, &t_class ); // actual type the_base = base_static ? member->t_base->actual_type : member->t_base; // this str = S_name(member->xid); return string(the_base->c_name()) + std::string(".") + str; } //----------------------------------------------------------------------------- // name: find_func_match() // desc: ... //----------------------------------------------------------------------------- Chuck_Func * find_func_match( Chuck_Func * up, a_Exp args, t_CKBOOL implicit ) { a_Exp e; a_Arg_List e1; t_CKUINT count; Chuck_Func * func; // see if args is nil if( args && args->type == &t_void ) args = NULL; // up is the list of functions in single class / namespace while( up ) { func = up; // loop while( func ) { e = args; e1 = func->def->arg_list; count = 1; // check arguments against the definition while( e ) { // check for extra arguments if( e1 == NULL ) goto moveon; // no match if( !isa( e->type, e1->type ) ) { // TODO: fix this for overload implicit cast (multiple matches) if( implicit && *e->type == t_int && *e1->type == t_float ) { // int to float e->cast_to = &t_float; } else goto moveon; // type mismatch } e = e->next; e1 = e1->next; count++; } // check for extra arguments if( e1 == NULL ) return func; moveon: // next func func = func->next; } // go up if( up->up ) up = up->up->func_ref; else up = NULL; } // not found return NULL; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp exp_func, a_Exp args, t_CKFUNC & ck_func, int linepos ) { Chuck_Func * func = NULL; Chuck_Func * up = NULL; // type check the func t_CKTYPE f = exp_func->type = type_engine_check_exp( env, exp_func ); if( !f ) return NULL; // void type for args t_CKTYPE a = &t_void; // make sure we have a function if( !isa( f, &t_function ) ) { EM_error2( exp_func->linepos, "function call using a non-function value" ); return NULL; } // copy the func up = f->func; // check the arguments if( args ) { a = type_engine_check_exp( env, args ); if( !a ) return NULL; } // look for a match func = find_func_match( up, args, FALSE ); // look for a match (with implicit cast) if( !func ) func = find_func_match( up, args, TRUE ); // no func if( !func ) { // if primary if( exp_func->s_type == ae_exp_primary && exp_func->primary.s_type == ae_primary_var ) { EM_error2( exp_func->linepos, "argument type(s) do not match:" ); EM_error2( exp_func->linepos, "... for function '%s(...)' ...", S_name(exp_func->primary.var) ); } else if( exp_func->s_type == ae_exp_dot_member ) { EM_error2( exp_func->linepos, "arguments type(s) do not match:" ); EM_error2( exp_func->linepos, "... for function '%s(...)' ...", type_engine_print_exp_dot_member( env, &exp_func->dot_member ).c_str() ); } else { EM_error2( exp_func->linepos, "argument type(s) do not match for function ..." ); } EM_error2( exp_func->linepos, "...(please check the argument types)" ); return NULL; } // recheck the type with new name if( exp_func->s_type == ae_exp_primary && exp_func->primary.s_type == ae_primary_var ) { // set the new name // TODO: clear old exp_func->primary.var = insert_symbol(func->name.c_str()); // make sure the type is still the name if( *exp_func->type != *type_engine_check_exp( env, exp_func ) ) { // error EM_error2( exp_func->linepos, "internal error: function type different on second check..." ); return NULL; } } else if( exp_func->s_type == ae_exp_dot_member ) { // set the new name // TODO: clear old exp_func->dot_member.xid = insert_symbol(func->name.c_str()); /* // TODO: figure if this is necessary - it type checks things twice! // make sure the type is still the name if( *exp_func->type != *type_engine_check_exp( env, exp_func ) ) { // error EM_error2( exp_func->linepos, "internal error: function type different on second check..." ); return NULL; } */ } else assert( FALSE ); ck_func = func; return func->def->ret_type; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_func_call() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_func_call( Chuck_Env * env, a_Exp_Func_Call func_call ) { // type check it return type_engine_check_exp_func_call( env, func_call->func, func_call->args, func_call->ck_func, func_call->linepos ); } //----------------------------------------------------------------------------- // name: type_engine_check_exp_dot_member() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_dot_member( Chuck_Env * env, a_Exp_Dot_Member member ) { Chuck_Value * value = NULL; Chuck_Type * the_base = NULL; t_CKBOOL base_static = FALSE; string str; // type check the base member->t_base = type_engine_check_exp( env, member->base ); if( !member->t_base ) return NULL; // is the base a class/namespace or a variable base_static = isa( member->t_base, &t_class ); // actual type the_base = base_static ? member->t_base->actual_type : member->t_base; // have members? if( !the_base->info ) { // base type does not have members EM_error2( member->base->linepos, "type '%s' does not have members - invalid use in dot expression", the_base->c_name() ); return NULL; } // this str = S_name(member->xid); if( str == "this" ) { // uh if( base_static ) { EM_error2( member->linepos, "keyword 'this' must be associated with object instance..." ); return NULL; } // in member func if( env->func && !env->func->is_member ) { EM_error2( member->linepos, "keyword 'this' cannot be used inside static functions..." ); return NULL; } return env->class_def; } // find the value value = type_engine_find_value( the_base, member->xid ); if( !value ) { // can't find member EM_error2( member->base->linepos, "class '%s' has no member '%s'", the_base->c_name(), S_name(member->xid) ); return NULL; } // make sure if( base_static && value->is_member ) { // this won't work EM_error2( member->linepos, "cannot access member '%s.%s' without object instance...", the_base->c_name(), S_name(member->xid) ); return NULL; } return value->type; } //----------------------------------------------------------------------------- // name: type_engine_check_exp_array() // desc: ... //----------------------------------------------------------------------------- t_CKTYPE type_engine_check_exp_array( Chuck_Env * env, a_Exp_Array array ) { // verify there are no errors from the parser... if( !verify_array( array->indices ) ) return NULL; // type check the base t_CKTYPE t_base = type_engine_check_exp( env, array->base ); if( !t_base ) return NULL; // dimension if( array->indices->depth > t_base->array_depth ) { EM_error2( array->linepos, "array subscripts (%i) exceeds defined dimension (%i)", array->indices->depth, t_base->array_depth ); return NULL; } // type check the index t_CKTYPE t_index = type_engine_check_exp( env, array->indices->exp_list ); if( !t_index ) return NULL; // cycle through each exp a_Exp e = array->indices->exp_list; // count the dimension t_CKUINT depth = 0; while( e ) { // increment depth++; // check if index is of valid type if( !isa( e->type, &t_int ) && !isa( e->type, &t_string ) ) { // not int or string EM_error2( e->linepos, "array index %i must be of type 'int' or 'string', not '%s'", depth, e->type->c_name() ); return NULL; } // advance the list e = e->next; } // sanity assert( array->indices->depth == depth ); t_CKTYPE t = NULL; // make sure depth <= max if( depth == t_base->array_depth ) { // the original type t = array->base->type->array_type; } else { // partial t = array->base->type->copy( env ); // remainder t->array_depth -= depth; } return t; } //----------------------------------------------------------------------------- // name: type_engine_check_class_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_class_def( Chuck_Env * env, a_Class_Def class_def ) { // make new type for class def t_CKTYPE the_class = NULL; // the parent class t_CKTYPE t_parent = NULL; // the return type t_CKBOOL ret = TRUE; // the class body a_Class_Body body = class_def->body; // make sure inheritance // TODO: sort! if( class_def->ext ) { // if extend if( class_def->ext->extend_id ) { // find the type t_parent = type_engine_find_type( env, class_def->ext->extend_id ); if( !t_parent ) { EM_error2( class_def->ext->linepos, "undefined super class '%s' in definition of class '%s'", type_path(class_def->ext->extend_id), S_name(class_def->name->xid) ); return FALSE; } // must not be primitive if( isprim( t_parent ) ) { EM_error2( class_def->ext->linepos, "cannot extend primitive type '%s'", t_parent->c_name() ); EM_error2( class_def->ext->linepos, "...(note: primitives types are 'int', 'float', 'time', and 'dur')" ); return FALSE; } // if not complete if( t_parent->is_complete == FALSE ) { EM_error2( class_def->ext->linepos, "cannot extend incomplete type '%s'", t_parent->c_name() ); EM_error2( class_def->ext->linepos, "...(note: the parent's declaration must preceed child's)" ); return FALSE; } } // TODO: interface } // by default object if( !t_parent ) t_parent = &t_object; // check for fun assert( env->context != NULL ); assert( class_def->type != NULL ); assert( class_def->type->info != NULL ); // retrieve the new type (created in scan_class_def) the_class = class_def->type; // set fields not set in scan the_class->parent = t_parent; // inherit ugen_info data from parent PLD the_class->ugen_info = t_parent->ugen_info; // set the beginning of data segment to after the parent the_class->info->offset = t_parent->obj_size; // duplicate the parent's virtual table the_class->info->obj_v_table = t_parent->info->obj_v_table; // set the new type as current env->nspc_stack.push_back( env->curr ); env->curr = the_class->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = the_class; // reset the nest list env->class_scope = 0; // type check the body while( body && ret ) { // check the section switch( body->section->s_type ) { case ae_section_stmt: // flag as having a constructor env->class_def->has_constructor |= (body->section->stmt_list->stmt != NULL); ret = type_engine_check_stmt_list( env, body->section->stmt_list ); break; case ae_section_func: // set to complete env->class_def->is_complete = TRUE; ret = type_engine_check_func_def( env, body->section->func_def ); // back env->class_def->is_complete = FALSE; break; case ae_section_class: // check it ret = type_engine_check_class_def( env, body->section->class_def ); break; } // move to the next section body = body->next; } // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); // if ok if( ret ) { // set the object size the_class->obj_size = the_class->info->offset; // set complete the_class->is_complete = TRUE; } if( !ret ) { // delete the class definition SAFE_RELEASE( class_def->type ); // set the thing to NULL the_class = NULL; } return ret; } //----------------------------------------------------------------------------- // name: type_engine_check_func_def() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_func_def( Chuck_Env * env, a_Func_Def f ) { Chuck_Value * value = NULL; Chuck_Func * func = NULL; Chuck_Type * parent = NULL; Chuck_Value * override = NULL; Chuck_Value * v = NULL; Chuck_Func * parent_func = NULL; a_Arg_List arg_list = NULL; t_CKBOOL parent_match = FALSE; string func_name = S_name(f->name); t_CKUINT count = 0; t_CKBOOL has_code = FALSE; // use this for both user and imported // see if we are already in a function definition if( env->func != NULL ) { EM_error2( f->linepos, "nested function definitions are not (yet) allowed" ); return FALSE; } // get the func func = f->ck_func; // get the value value = func->value_ref; // make sure assert( func != NULL && value != NULL ); // look up the value in the parent class if( env->class_def && ( override = type_engine_find_value( env->class_def->parent, f->name ) ) ) { // see if the target is a function if( !isa( override->type, &t_function ) ) { EM_error2( f->linepos, "function name '%s' conflicts with previously defined value...", S_name(f->name) ); EM_error2( f->linepos, "from super class '%s'...", override->owner_class->c_name() ); return FALSE; } } // make sure a code segment is in stmt - else we should push scope assert( !f->code || f->code->s_type == ae_stmt_code ); // if override if( override ) { // make reference to parent // TODO: ref count func->up = override; } // make sure return type is not NULL assert( f->ret_type != NULL ); // only class functions can be pure if( !env->class_def && f->static_decl == ae_key_abstract ) { EM_error2( f->linepos, "non-class function cannot be declared as 'pure'..." ); EM_error2( f->linepos, "...at function '%s'", S_name(f->name) ); goto error; } // figure out if the function has code associated with it if( f->s_type == ae_func_user ) has_code = ( f->code != NULL ); else has_code = (f->dl_func_ptr != NULL); // imported // if interface, then cannot have code if( env->class_def && env->class_def->def && env->class_def->def->iface && has_code ) { EM_error2( f->linepos, "interface function signatures cannot contain code..." ); EM_error2( f->linepos, "...at function '%s'", S_name(f->name) ); goto error; } // if pure, then cannot have code if( f->static_decl == ae_key_abstract && has_code ) { EM_error2( f->linepos, "'pure' function signatures cannot contain code..." ); EM_error2( f->linepos, "...at function '%s'", S_name(f->name) ); goto error; } // yeah if( f->static_decl != ae_key_abstract && !has_code ) { EM_error2( f->linepos, "function declaration must contain code..." ); EM_error2( f->linepos, "(unless in interface, or is declared 'pure')" ); EM_error2( f->linepos, "...at function '%s'", S_name(f->name) ); goto error; } // if overriding super class function, then check signatures if( env->class_def ) { // get parent parent = env->class_def->parent; while( parent && !parent_match ) { if(( v = type_engine_find_value( env->class_def->parent, f->name ) )) { // see if the target is a function if( !isa( v->type, &t_function ) ) { EM_error2( f->linepos, "function name '%s' conflicts with previously defined value...", S_name(f->name) ); EM_error2( f->linepos, "from super class '%s'...", v->owner_class->c_name() ); goto error; } // parent func parent_func = v->func_ref; // go through all overloading while( parent_func && !parent_match ) { // match the prototypes string err; if( !type_engine_compat_func( f, parent_func->def, f->linepos, err, FALSE ) ) { // next parent_func = parent_func->next; // move on continue; } /*{ EM_error2( f->linepos, "function '%s.%s' resembles '%s.%s' but cannot override...", env->class_def->c_name(), S_name(f->name), value->owner_class->c_name(), S_name(f->name) ); if( err != "" ) EM_error2( f->linepos, "...(reason: %s)", err.c_str() ); goto error; }*/ // see if parent function is static if( parent_func->def->static_decl == ae_key_static ) { EM_error2( f->linepos, "function '%s.%s' resembles '%s.%s' but cannot override...", env->class_def->c_name(), S_name(f->name), v->owner_class->c_name(), S_name(f->name) ); EM_error2( f->linepos, "...(reason: '%s.%s' is declared as 'static')", v->owner_class->c_name(), S_name(f->name) ); goto error; } // see if function is static if( f->static_decl == ae_key_static ) { EM_error2( f->linepos, "function '%s.%s' resembles '%s.%s' but cannot override...", env->class_def->c_name(), S_name(f->name), v->owner_class->c_name(), S_name(f->name) ); EM_error2( f->linepos, "...(reason: '%s.%s' is declared as 'static')", env->class_def->c_name(), S_name(f->name) ); goto error; } // see if function is pure if( f->static_decl == ae_key_abstract ) { EM_error2( f->linepos, "function '%s.%s' resembles '%s.%s' but cannot override...", env->class_def->c_name(), S_name(f->name), v->owner_class->c_name(), S_name(f->name) ); EM_error2( f->linepos, "...(reason: '%s.%s' is declared as 'pure')", env->class_def->c_name(), S_name(f->name) ); goto error; } // make sure returns are equal if( *(f->ret_type) != *(parent_func->def->ret_type) ) { EM_error2( f->linepos, "function signatures differ in return type..." ); EM_error2( f->linepos, "function '%s.%s' matches '%s.%s' but cannot override...", env->class_def->c_name(), S_name(f->name), v->owner_class->c_name(), S_name(f->name) ); goto error; } // match parent_match = TRUE; // update virtual table func->vt_index = parent_func->vt_index; assert( func->vt_index < env->curr->obj_v_table.funcs.size() ); env->curr->obj_v_table.funcs[func->vt_index] = func; // update name func_name = parent_func->name; func->name = func_name; value->name = func_name; } } // move to next parent parent = parent->parent; } } // if not override, make entry in virtual table if( func->is_member && !parent_match ) { // remember virtual table index func->vt_index = env->curr->obj_v_table.funcs.size(); // append to virtual table env->curr->obj_v_table.funcs.push_back( func ); } // set the current function to this env->func = func; // push the value stack env->curr->value.push(); // look up types for the function arguments arg_list = f->arg_list; // count count = 1; // loop over arguments while( arg_list ) { // make sure type != NULL assert( arg_list->type != NULL ); // get the value v = arg_list->var_decl->value; // make sure value != NULL assert( v != NULL ); // look up in scope: later if( env->curr->lookup_value( arg_list->var_decl->xid, FALSE ) ) { EM_error2( arg_list->linepos, "in function '%s':", S_name(f->name) ); EM_error2( arg_list->linepos, "argument %i '%s' is already defined in this scope", count, S_name(arg_list->var_decl->xid) ); goto error; } // add as value env->curr->value.add( arg_list->var_decl->xid, v ); // increment count count++; // next arg arg_list = arg_list->next; } // type check the code assert( f->code == NULL || f->code->s_type == ae_stmt_code ); if( f->code && !type_engine_check_code_segment( env, &f->code->stmt_code, FALSE ) ) { EM_error2( 0, "...in function '%s'", S_name(f->name) ); goto error; } // if imported, add the stack depth if( f->s_type == ae_func_builtin ) { // set the stack depth? func->code->stack_depth = f->stack_depth; // if member add room for this // done: if( func->is_member ) func->code->stack_depth += sizeof(t_CKUINT); } // pop the value stack env->curr->value.pop(); // clear the env's function definition env->func = NULL; return TRUE; error: // clean up env->func = NULL; // func->release(); return FALSE; } //----------------------------------------------------------------------------- // name: lookup_type() // desc: lookup type in the env //----------------------------------------------------------------------------- Chuck_Type * Chuck_Namespace::lookup_type( const string & name, t_CKINT climb ) { Chuck_Type * t = type.lookup( name, climb ); if( climb > 0 && !t && parent ) return parent->lookup_type( name, climb ); return t; } //----------------------------------------------------------------------------- // name: lookup_type() // desc: lookup type in the env //----------------------------------------------------------------------------- Chuck_Type * Chuck_Namespace::lookup_type( S_Symbol name, t_CKINT climb ) { Chuck_Type * t = type.lookup( name, climb ); if( climb > 0 && !t && parent ) return parent->lookup_type( name, climb ); return t; } //----------------------------------------------------------------------------- // name: lookup_value() // desc: lookup value in the env //----------------------------------------------------------------------------- Chuck_Value * Chuck_Namespace::lookup_value( const string & name, t_CKINT climb ) { Chuck_Value * v = value.lookup( name, climb ); if( climb > 0 && !v && parent ) return parent->lookup_value( name, climb ); return v; } //----------------------------------------------------------------------------- // name: lookup_value() // desc: lookup value in the env //----------------------------------------------------------------------------- Chuck_Value * Chuck_Namespace::lookup_value( S_Symbol name, t_CKINT climb ) { Chuck_Value * v = value.lookup( name, climb ); if( climb > 0 && !v && parent ) return parent->lookup_value( name, climb ); return v; } //----------------------------------------------------------------------------- // name: lookup_func() // desc: lookup func in the env //----------------------------------------------------------------------------- Chuck_Func * Chuck_Namespace::lookup_func( const string & name, t_CKINT climb ) { Chuck_Func * f = func.lookup( name, climb ); if( climb > 0 && !f && parent ) return parent->lookup_func( name, climb ); return f; } //----------------------------------------------------------------------------- // name: lookup_func() // desc: lookup func in the env //----------------------------------------------------------------------------- Chuck_Func * Chuck_Namespace::lookup_func( S_Symbol name, t_CKINT climb ) { Chuck_Func * f = func.lookup( name, climb ); if( climb > 0 && !f && parent ) return parent->lookup_func( name, climb ); return f; } //----------------------------------------------------------------------------- // name: get_types() // desc: get top level types //----------------------------------------------------------------------------- void Chuck_Namespace::get_types( vector & out ) { // temporary vector vector list; // get it from the scope this->type.get_toplevel( list ); // clear out.clear(); // copy the list - cast for( t_CKUINT i = 0; i < list.size(); i++ ) out.push_back( (Chuck_Type *)list[i] ); } //----------------------------------------------------------------------------- // name: get_values() // desc: get top level values //----------------------------------------------------------------------------- void Chuck_Namespace::get_values( vector & out ) { // temporary vector vector list; // get it from the scope this->value.get_toplevel( list ); // clear out.clear(); // copy the list - cast for( t_CKUINT i = 0; i < list.size(); i++ ) out.push_back( (Chuck_Value *)list[i] ); } //----------------------------------------------------------------------------- // name: get_funcs() // desc: get top level functions //----------------------------------------------------------------------------- void Chuck_Namespace::get_funcs( vector & out ) { // temporary vector vector list; // get it from the scope this->type.get_toplevel( list ); // clear out.clear(); // copy the list - cast for( t_CKUINT i = 0; i < list.size(); i++ ) out.push_back( (Chuck_Func *)list[i] ); } //----------------------------------------------------------------------------- // name: operator == // desc: ... //----------------------------------------------------------------------------- t_CKBOOL operator ==( const Chuck_Type & lhs, const Chuck_Type & rhs ) { // check id if( lhs.xid != rhs.xid ) return FALSE; // check array depth if( lhs.array_depth != rhs.array_depth ) return FALSE; // check array type if( lhs.array_depth && (*lhs.actual_type != *rhs.actual_type) ) return FALSE; // if user-defined type if( lhs.xid == te_user ) { // check name if( lhs.name != rhs.name ) return FALSE; // check owner if( lhs.owner != rhs.owner ) return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: operator != // desc: ... //----------------------------------------------------------------------------- t_CKBOOL operator !=( const Chuck_Type & lhs, const Chuck_Type & rhs ) { return !( lhs == rhs ); } //----------------------------------------------------------------------------- // name: equals() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL equals( Chuck_Type * lhs, Chuck_Type * rhs ) { return (*lhs) == (*rhs); } //----------------------------------------------------------------------------- // name: operator <= // desc: ... //----------------------------------------------------------------------------- t_CKBOOL operator <=( const Chuck_Type & lhs, const Chuck_Type & rhs ) { // check to see if type L == type R if( lhs == rhs ) return TRUE; // if lhs is a child of rhs const Chuck_Type * curr = lhs.parent; while( curr ) { if( *curr == rhs ) return TRUE; curr = curr->parent; } // if lhs is null and rhs is a object if( lhs == t_null && (rhs <= t_object) ) return TRUE; return FALSE; } //----------------------------------------------------------------------------- // name: isa() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL isa( Chuck_Type * lhs, Chuck_Type * rhs ) { return (*lhs) <= (*rhs); } //----------------------------------------------------------------------------- // name: ~Chuck_Context() // desc: ... //----------------------------------------------------------------------------- Chuck_Context::~Chuck_Context() { // if has error, then delete nspc. otherwise, the nspc stays as part of // the type system, since many things have been added to it if( has_error ) { SAFE_DELETE( nspc ); // delete the types - can't do this since the type system and vm still use // for( t_CKINT i = 0; i < new_types.size(); i++ ) // new_types[i]->release(); // clear it new_types.clear(); } // TODO: delete abstract syntax tree * } //----------------------------------------------------------------------------- // name: add_commit_candidate() // desc: ... //----------------------------------------------------------------------------- void Chuck_Context::add_commit_candidate( Chuck_Namespace * nspc ) { // add for commit commit_map[nspc] = nspc; } //----------------------------------------------------------------------------- // name: commit() // desc: ... //----------------------------------------------------------------------------- void Chuck_Context::commit() { std::map::iterator iter; // loop through for( iter = commit_map.begin(); iter != commit_map.end(); iter++ ) { // commit (*iter).second->commit(); } // clear commit_map.clear(); } //----------------------------------------------------------------------------- // name: rollback() // desc: ... //----------------------------------------------------------------------------- void Chuck_Context::rollback() { std::map::iterator iter; // loop through for( iter = commit_map.begin(); iter != commit_map.end(); iter++ ) { // rollback (*iter).second->rollback(); } // clear commit_map.clear(); } //----------------------------------------------------------------------------- // name: type_engine_check_reserved() // desc: ... //-------------------------------------------------------------------------- t_CKBOOL type_engine_check_reserved( Chuck_Env * env, const string & xid, int pos ) { // key word? if( env->key_words[xid] ) { EM_error2( pos, "illegal use of keyword '%s'.", xid.c_str() ); return TRUE; } // key value? if( env->key_values[xid] ) { EM_error2( pos, "illegal re-declaration of reserved value '%s'.", xid.c_str() ); return TRUE; } // key type? if( env->key_types[xid] ) { EM_error2( pos, "illegal use of reserved type id '%s'.", xid.c_str() ); return TRUE; } return FALSE; } //----------------------------------------------------------------------------- // name: type_engine_check_reserved() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_reserved( Chuck_Env * env, S_Symbol xid, int pos ) { return type_engine_check_reserved( env, string(S_name(xid)), pos ); } //----------------------------------------------------------------------------- // name: type_engine_check_primitive() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_check_primitive( Chuck_Type * type ) { return ( isa(type, &t_int) || isa(type, &t_float) || isa(type, &t_dur) || isa(type, &t_time) ) && ( type->array_depth == 0 ); } t_CKBOOL isprim( Chuck_Type * type ) { return type_engine_check_primitive( type ); } t_CKBOOL isobj( Chuck_Type * type ) { return !type_engine_check_primitive( type ); } t_CKBOOL isfunc( Chuck_Type * type ) { return isa( type, &t_function ); } //----------------------------------------------------------------------------- // name: type_engine_find_common_anc() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_find_common_anc( Chuck_Type * lhs, Chuck_Type * rhs ) { // check to see if either is child of other if( isa( lhs, rhs ) ) return rhs; if( isa( rhs, lhs ) ) return lhs; // move up Chuck_Type * t = lhs->parent; // not at root while( t ) { // check and see again if( isa( rhs, t ) ) return t; // move up t = t->parent; } // didn't find return NULL; } //----------------------------------------------------------------------------- // name: type_path() // desc: ... //----------------------------------------------------------------------------- const char * type_path( a_Id_List path ) { static string str; // clear it str = ""; // loop over path while( path ) { // concatenate str += S_name(path->xid); // add . if( path->next ) str += "."; // advance path = path->next; } return str.c_str(); } //----------------------------------------------------------------------------- // name: type_engine_find_type() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_find_type( Chuck_Namespace * nspc, S_Symbol xid ) { Chuck_Type * type = NULL; if( !nspc) return NULL; // -1 for base if(( type = nspc->lookup_type( xid, -1 ) )) return type; return NULL; } //----------------------------------------------------------------------------- // name: type_engine_get_deprecate() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_get_deprecate( Chuck_Env * env, const string & from, string & to ) { // find mapping if( env->deprecated.find( from ) == env->deprecated.end() ) return FALSE; // return to = env->deprecated[from]; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_find_deprecated_type() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_find_deprecated_type( Chuck_Env * env, a_Id_List path ) { S_Symbol xid = NULL; Chuck_Type * t = NULL; std::string actual; // find mapping if( !type_engine_get_deprecate( env, S_name(path->xid), actual ) ) return NULL; // get base type Chuck_Type * type = env->curr->lookup_type( actual, TRUE ); if( !type ) return NULL; else { // check level if( env->deprecate_level < 2 ) { EM_error2( path->linepos, "deprecated: '%s' --> use: '%s'...", type_path( path ), actual.c_str() ); } } return type; } //----------------------------------------------------------------------------- // name: type_engine_find_type() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_find_type( Chuck_Env * env, a_Id_List path ) { S_Symbol xid = NULL; Chuck_Type * t = NULL; // get base type Chuck_Type * type = env->curr->lookup_type( path->xid, TRUE ); if( !type ) { // check level if( env->deprecate_level > 0 ) type = type_engine_find_deprecated_type( env, path ); // error if( !type ) { EM_error2( path->linepos, "undefined type '%s'...", type_path( path ) ); return NULL; } } // start the namespace Chuck_Namespace * nspc = type->info; path = path->next; // loop while( path != NULL ) { // get the id xid = path->xid; // look for the type in the namespace t = type_engine_find_type( nspc, xid ); // look in parent while( !t && type && type->parent ) { t = type_engine_find_type( type->parent->info, xid ); type = type->parent; } // can't find if( !t ) { // error EM_error2( path->linepos, "undefined type '%s'...", type_path( path ) ); EM_error2( path->linepos, "...(cannot find class '%s' in namespace '%s')", S_name(xid), nspc->name.c_str() ); return NULL; } // set the type type = t; // update nspc if( type ) nspc = type->info; // advance path = path->next; } return type; } //----------------------------------------------------------------------------- // name: type_engine_find_value() // desc: ... //----------------------------------------------------------------------------- Chuck_Value * type_engine_find_value( Chuck_Type * type, S_Symbol xid ) { return type_engine_find_value( type, string(S_name(xid)) ); } //----------------------------------------------------------------------------- // name: type_engine_find_value() // desc: ... //----------------------------------------------------------------------------- Chuck_Value * type_engine_find_value( Chuck_Type * type, const string & xid ) { Chuck_Value * value = NULL; if( !type ) return NULL; if( !type->info ) return NULL; // -1 for base if(( value = type->info->lookup_value( xid, -1 ) )) return value; if( type->parent ) return type_engine_find_value( type->parent, xid ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_find_value() // desc: from env... //----------------------------------------------------------------------------- Chuck_Value * type_engine_find_value( Chuck_Env * env, const string & xid, t_CKBOOL climb, int linepos ) { Chuck_Value * value = NULL; string actual; // look up if(( value = env->curr->lookup_value( xid, climb ) )) return value; // see if deprecated if climb if( climb ) { if( !type_engine_get_deprecate( env, xid, actual ) ) return NULL; // get base type value = env->curr->lookup_value( actual, TRUE ); if( !value ) return NULL; else { // check level if( env->deprecate_level < 2 ) { EM_error2( linepos, "deprecated: '%s' --> use: '%s'...", xid.c_str(), actual.c_str() ); } } } return value; } //----------------------------------------------------------------------------- // name: type_engine_find_nspc() // desc: ... //----------------------------------------------------------------------------- Chuck_Namespace * type_engine_find_nspc( Chuck_Env * env, a_Id_List path ) { Chuck_Namespace * nspc = NULL; // if the first if global, move to the next if( path && !strcmp( S_name(path->xid), "global" ) ) path = path->next; // global namespace if( path == NULL ) return env->global(); // find the type Chuck_Type * type = type_engine_find_type( env, path ); if( type == NULL ) return NULL; // copy the nspc nspc = type->info; if( nspc == NULL ) { // primitive if( isprim( type ) ) { // error EM_error2( 0, "primitive type '%s' has no namespace and cannot be extended...", type->c_name() ); return NULL; } else { // internal error EM_error2( 0, "internal error: type '%s' without namespace...", type->c_name() ); return NULL; } } return nspc; } //----------------------------------------------------------------------------- // name: type_engine_compat_func() // desc: see if two function signatures are compatible //----------------------------------------------------------------------------- t_CKBOOL type_engine_compat_func( a_Func_Def lhs, a_Func_Def rhs, int pos, string & err, t_CKBOOL print ) { // make sure public/private/protected/function match if( lhs->func_decl != rhs->func_decl ) { if( print ) { EM_error2( pos, "function signatures differ in access modifiers..." ); EM_error2( pos, "(both must be one of public/private/protected/function)..." ); } return FALSE; } a_Arg_List e1 = lhs->arg_list; a_Arg_List e2 = rhs->arg_list; t_CKUINT count = 1; // check arguments against the definition while( e1 && e2 ) { // make sure assert( e1->type && e2->type ); // match types if( *e1->type != *e2->type ) { if( print ) EM_error2( pos, "function signatures differ in argument %i's type...", count ); return FALSE; } e1 = e1->next; e2 = e2->next; count++; } // anything left if( e1 != NULL || e2 != NULL ) { if( print ) EM_error2( pos, "function signatures differ in number of arguments..." ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_import_class_begin() // desc: import existing base class, such as Object or Event // must be completed by type_engine_import_class_end() //----------------------------------------------------------------------------- Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, Chuck_Type * type, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor ) { Chuck_Value * value = NULL; Chuck_Type * type_type = NULL; // make sure there is not namesapce if( type->info != NULL ) { // error EM_error2( 0, "during import: class '%s' already imported...", type->c_name() ); return NULL; } // allocate namespace for type type->info = new Chuck_Namespace; // add reference SAFE_ADD_REF(type->info); // name it type->info->name = type->name; // set the parent namespace type->info->parent = where; // add reference SAFE_ADD_REF(type->info->parent); // if pre constructor if( pre_ctor != 0 ) { // flag it type->has_constructor = TRUE; // allocate vm code for pre_ctor type->info->pre_ctor = new Chuck_VM_Code; // add pre_ctor type->info->pre_ctor->native_func = (t_CKUINT)pre_ctor; // mark type as ctor type->info->pre_ctor->native_func_type = Chuck_VM_Code::NATIVE_CTOR; // specify that we need this type->info->pre_ctor->need_this = TRUE; // no arguments to preconstructor other than self type->info->pre_ctor->stack_depth = sizeof(t_CKUINT); } // if destructor if( dtor != 0 ) { // flag it type->has_destructor = TRUE; // allocate vm code for dtor type->info->dtor = new Chuck_VM_Code; // add dtor type->info->dtor->native_func = (t_CKUINT)dtor; // mark type as dtor type->info->dtor->native_func_type = Chuck_VM_Code::NATIVE_DTOR; // specify that we need this type->info->dtor->need_this = TRUE; // no arguments to destructor other than self type->info->dtor->stack_depth = sizeof(t_CKUINT); } // set the beginning of the data segment after parent if( type->parent ) { type->info->offset = type->parent->obj_size; // duplicate parent's virtual table assert( type->parent->info != NULL ); type->info->obj_v_table = type->parent->info->obj_v_table; } // set the owner namespace type->owner = where; // add reference SAFE_ADD_REF(type->owner); // set the size, which is always the width of a pointer type->size = sizeof(t_CKUINT); // set the object size type->obj_size = 0; // TODO // flag as complete type->is_complete = TRUE; // make type type_type = t_class.copy( env ); type_type->actual_type = type; // SAFE_REF_ASSIGN( type_type->actual_type, type ); // make value value = new Chuck_Value( type_type, type->name ); value->owner = where; // SAFE_REF_ASSIGN( value->owner, where ); value->is_const = TRUE; value->is_member = FALSE; // add to env where->value.add( value->name, value ); // make the type current env->nspc_stack.push_back( env->curr ); env->curr = type->info; // push the class def env->class_stack.push_back( env->class_def ); env->class_def = type; // ref count type->add_ref(); return type; } //----------------------------------------------------------------------------- // name: type_engine_import_class_begin() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, const char * name, const char * parent_str, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor ) { // which namespace Chuck_Type * parent = NULL; Chuck_Type * type = NULL; a_Id_List parent_list = NULL; // if parent is specified if( strcmp( parent_str, "") ) { // get parent parent_list = str2list( parent_str ); parent = type_engine_find_type( env, parent_list ); if( !parent ) goto error; } else // if no parent specified, then extend Object { parent = &t_object; } // allocate type type = new Chuck_Type( te_user, name, parent, sizeof(void *) ); // add to namespace - TODO: handle failure, remove from where where->type.add( name, type ); // do the rest if( !type_engine_import_class_begin( env, type, where, pre_ctor, dtor ) ) goto error; // done goto cleanup; error: // error EM_error2( 0, "... during import of class '%s'", name ); // free SAFE_DELETE( type ); cleanup: // cleanup delete_id_list( parent_list ); return type; } //----------------------------------------------------------------------------- // name: type_engine_import_ugen_begin() // desc: ... //----------------------------------------------------------------------------- Chuck_Type * type_engine_import_ugen_begin( Chuck_Env * env, const char * name, const char * parent, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor, f_tick tick, f_pmsg pmsg, t_CKUINT num_ins, t_CKUINT num_outs ) { Chuck_Type * type = NULL; Chuck_UGen_Info * info = NULL; // construct class if( !(type = type_engine_import_class_begin( env, name, parent, where, pre_ctor, dtor ) ) ) return FALSE; // make sure parent is ugen assert( type->parent != NULL ); if( !isa( type->parent, &t_ugen ) ) { // error EM_error2( 0, "imported class '%s' does not have a ugen as parent", type->c_name() ); return FALSE; } // do the ugen part info = new Chuck_UGen_Info; info->add_ref(); info->tick = type->parent->ugen_info->tick; info->pmsg = type->parent->ugen_info->pmsg; info->num_ins = type->parent->ugen_info->num_ins; info->num_outs = type->parent->ugen_info->num_outs; if( tick ) info->tick = tick; if( pmsg ) info->pmsg = pmsg; if( num_ins != 0xffffffff ) info->num_ins = num_ins; if( num_outs != 0xffffffff ) info->num_outs = num_outs; // set in type type->ugen_info = info; return type; } //----------------------------------------------------------------------------- // name: type_engine_import_class_end() // desc: finish import of a class //----------------------------------------------------------------------------- t_CKBOOL type_engine_import_class_end( Chuck_Env * env ) { if( !env->class_def ) { // error EM_error2( 0, "import: too many class_end called..." ); return FALSE; } // set the object size env->class_def->obj_size = env->class_def->info->offset; // pop the class env->class_def = env->class_stack.back(); env->class_stack.pop_back(); // pop the namesapce env->curr = env->nspc_stack.back(); env->nspc_stack.pop_back(); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_import_mfun() // desc: import member function (must be between class_begin/end) //----------------------------------------------------------------------------- t_CKBOOL type_engine_import_mfun( Chuck_Env * env, Chuck_DL_Func * mfun ) { a_Func_Def func_def = NULL; // make sure we are in class if( !env->class_def ) { // error EM_error2( 0, "import error: import_mfun '%s' invoked between begin/end", mfun->name.c_str() ); return FALSE; } // make into func_def func_def = make_dll_as_fun( mfun, FALSE ); if( !func_def ) return FALSE; // add the function to class if( !type_engine_scan1_func_def( env, func_def ) ) return FALSE; if( !type_engine_scan2_func_def( env, func_def ) ) return FALSE; if( !type_engine_check_func_def( env, func_def ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_import_sfun() // desc: import static function (must be between class_begin/end) //----------------------------------------------------------------------------- t_CKBOOL type_engine_import_sfun( Chuck_Env * env, Chuck_DL_Func * sfun ) { a_Func_Def func_def = NULL; // make sure we are in class if( !env->class_def ) { // error EM_error2( 0, "import error: import_sfun '%s' invoked between begin/end", sfun->name.c_str() ); return FALSE; } // make into func_def func_def = make_dll_as_fun( sfun, TRUE ); // add the function to class if( !type_engine_scan1_func_def( env, func_def ) ) return FALSE; if( !type_engine_scan2_func_def( env, func_def ) ) return FALSE; if( !type_engine_check_func_def( env, func_def ) ) return FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_import_mvar() // desc: import member variable (must be between class_begin/end) //----------------------------------------------------------------------------- t_CKUINT type_engine_import_mvar( Chuck_Env * env, const char * type, const char * name, t_CKUINT is_const ) { // make sure we are in class if( !env->class_def ) { // error EM_error2( 0, "import error: import_mvar '%s' invoked between begin/end", name ); return CK_INVALID_OFFSET; } // make path t_CKUINT array_depth = 0; a_Id_List path = str2list( type, array_depth ); if( !path ) { // error EM_error2( 0, "... during mvar import '%s.%s'...", env->class_def->c_name(), name ); return CK_INVALID_OFFSET; } // make type decl a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 ); // check for array if( array_depth ) { // add the array type_decl->array = new_array_sub( NULL, 0 ); // set the depth type_decl->array->depth = array_depth; } // make var decl a_Var_Decl var_decl = new_var_decl( (char *)name, NULL, 0 ); // make var decl list a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 ); // make exp decl a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, FALSE, 0 ); // add it if( !type_engine_scan1_exp_decl( env, &exp_decl->decl ) || !type_engine_scan2_exp_decl( env, &exp_decl->decl ) || !type_engine_check_exp_decl( env, &exp_decl->decl ) ) { delete_id_list( path ); return CK_INVALID_OFFSET; } // cleanup delete_id_list( path ); // return the offset return var_decl->value->offset; } //----------------------------------------------------------------------------- // name: type_engine_import_svar() // desc: import static variable (must be between class_begin/end) //----------------------------------------------------------------------------- t_CKBOOL type_engine_import_svar( Chuck_Env * env, const char * type, const char * name, t_CKUINT is_const, t_CKUINT addr ) { // make sure we are in class if( !env->class_def ) { // error EM_error2( 0, "import error: import_svar '%s' invoked between begin/end", name ); return FALSE; } // make path a_Id_List path = str2list( type ); if( !path ) { // error EM_error2( 0, "... during svar import '%s.%s'...", env->class_def->c_name(), name ); return FALSE; } // make type decl a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 ); // make var decl a_Var_Decl var_decl = new_var_decl( (char *)name, NULL, 0 ); // make var decl list a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 ); // make exp decl a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, TRUE, 0 ); // add addr var_decl->addr = (void *)addr; // add it if( !type_engine_scan1_exp_decl( env, &exp_decl->decl ) || !type_engine_scan2_exp_decl( env, &exp_decl->decl ) || !type_engine_check_exp_decl( env, &exp_decl->decl ) ) { delete_id_list( path ); return FALSE; } // cleanup delete_id_list( path ); return TRUE; } //----------------------------------------------------------------------------- // name: type_engine_register_deprecate() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL type_engine_register_deprecate( Chuck_Env * env, const string & former, const string & latter ) { env->deprecated[former] = latter; return TRUE; } //----------------------------------------------------------------------------- // name: init_special() // desc: ... //----------------------------------------------------------------------------- void init_special( Chuck_VM_Object * obj ) { // reference - this is done when the reference is assigned // obj->add_ref(); // add to vector if( obj->m_v_ref ) obj->m_v_ref->push_back( obj ); } //----------------------------------------------------------------------------- // name: new_Chuck_Type() // desc: instantiate new chuck type //----------------------------------------------------------------------------- Chuck_Type * Chuck_Context::new_Chuck_Type() { // allocate Chuck_Type * type = new Chuck_Type; if( !type ) return NULL; // set v ref type->m_v_ref = &new_types; // initialize it init_special( type ); return type; } //----------------------------------------------------------------------------- // name: new_Chuck_Value() // desc: instantiate new chuck value //----------------------------------------------------------------------------- Chuck_Value * Chuck_Context::new_Chuck_Value( Chuck_Type * t, const string & name ) { // allocate Chuck_Value * value = new Chuck_Value( t, name ); if( !value ) return NULL; // set v ref value->m_v_ref = &new_values; // initialize it init_special( value ); return value; } //----------------------------------------------------------------------------- // name: new_Chuck_Func() // desc: instantiate new chuck func //----------------------------------------------------------------------------- Chuck_Func * Chuck_Context::new_Chuck_Func() { // allocate Chuck_Func * func = new Chuck_Func; if( !func ) return NULL; // set v ref func->m_v_ref = &new_funcs; // initialize it init_special( func ); return func; } //----------------------------------------------------------------------------- // name: new_Chuck_Namespace() // desc: instantiate new chuck namespace //----------------------------------------------------------------------------- Chuck_Namespace * Chuck_Context::new_Chuck_Namespace() { // allocate Chuck_Namespace * nspc = new Chuck_Namespace; if( !nspc ) return NULL; // set v ref nspc->m_v_ref = &new_nspc; // initialize it init_special( nspc ); return nspc; } //----------------------------------------------------------------------------- // name: new_array_type() // desc: instantiate new chuck type for some kind of array //----------------------------------------------------------------------------- Chuck_Type * new_array_type( Chuck_Env * env, Chuck_Type * array_parent, t_CKUINT depth, Chuck_Type * base_type, Chuck_Namespace * owner_nspc ) { // make new type Chuck_Type * t = env->context->new_Chuck_Type(); // set the id t->xid = te_array; // set the name t->name = base_type->name; // set the parent t->parent = array_parent; // add reference SAFE_ADD_REF(t->parent); // is a ref t->size = array_parent->size; // set the array depth t->array_depth = depth; // set the base type t->array_type = base_type; // add reference SAFE_ADD_REF(t->array_type); // set the namesapce t->info = array_parent->info; // add reference SAFE_ADD_REF(t->info); // set owner t->owner = owner_nspc; // add reference SAFE_ADD_REF(t->owner); // return the type return t; } //----------------------------------------------------------------------------- // name: new_Chuck_Namespace() // desc: instantiate new chuck namespace //----------------------------------------------------------------------------- t_CKBOOL verify_array( a_Array_Sub array ) { // verify there were no errors from the parser... if( array->err_num ) { if( array->err_num == 1 ) { EM_error2( array->linepos, "invalid format for array init [...][...]..." ); return FALSE; } else if( array->err_num == 2 ) { EM_error2( array->linepos, "partially empty array init [...][]..." ); return FALSE; } else { EM_error2( array->linepos, "internal error: unrecognized array error..." ); return FALSE; } } return TRUE; } //----------------------------------------------------------------------------- // name: str2list() // desc: convert str to list //----------------------------------------------------------------------------- a_Id_List str2list( const string & path ) { t_CKUINT dummy; return str2list( path, dummy ); } //----------------------------------------------------------------------------- // name: str2list() // desc: convert str to list //----------------------------------------------------------------------------- a_Id_List str2list( const string & path, t_CKUINT & array_depth ) { t_CKINT len = path.length(); t_CKINT i, j; string curr; a_Id_List list = NULL; char last = '\0'; // look for [] array_depth = 0; while( len > 2 && path[len-1] == ']' && path[len-2] == '[' ) { // flag it array_depth++; // shorten len len -= 2; } // loop backwards for( i = len - 1; i >= 0; i-- ) { char c = path[i]; // if not . if( c != '.' ) { // check to make sure valid if( ( c >= 'A' && c <= 'Z' ) || ( c >= 'a' && c <= 'z' ) || ( c == '_' ) || ( c >= '0' && c <= '9' ) ) { // add curr += c; } else { // error EM_error2( 0, "illegal character '%c' in path '%s'...", c, path.c_str() ); // delete delete_id_list( list ); return NULL; } } // add if( c == '.' || i == 0 ) { // make sure valid if( (i != 0 && last != '.' && last != '\0') || (i == 0 && c != '.') ) { char s; t_CKINT size = curr.length(); // reverse for( j = 0; j < size/2; j++ ) { // swap s = curr[j]; curr[j] = curr[size-j-1]; curr[size-j-1] = s; } // make a new id and put in list list = prepend_id_list( (char *)curr.c_str(), list, 0 ); // clear curr = ""; } else { // error EM_error2( 0, "path '%s' must not begin or end with '.'", path.c_str() ); // delete delete_id_list( list ); return NULL; } } // remember last last = c; } return list; } //----------------------------------------------------------------------------- // name: make_dll_arg_list() // desc: make an chuck dll function into arg list //----------------------------------------------------------------------------- a_Arg_List make_dll_arg_list( Chuck_DL_Func * dl_fun ) { a_Arg_List arg_list = NULL; a_Type_Decl type_decl = NULL; a_Var_Decl var_decl = NULL; a_Id_List type_path = NULL; a_Id_List name_path = NULL; a_Array_Sub array_sub = NULL; Chuck_DL_Value * arg = NULL; t_CKUINT array_depth = 0; t_CKUINT array_depth2 = 0; t_CKINT i = 0; // loop backwards for( i = dl_fun->args.size() - 1; i >= 0; i-- ) { // copy into variable arg = dl_fun->args[i]; // path type_path = str2list( arg->type, array_depth ); if( !type_path ) { // error EM_error2( 0, "...at argument '%i'...", i+1 ); // delete the arg list // delete_arg_list( arg_list ); return NULL; } // type type_decl = new_type_decl( type_path, FALSE, 0 ); // TODO: fix this assert( type_decl ); // var name_path = str2list( arg->name, array_depth2 ); // sanity if( array_depth && array_depth2 ) { // error EM_error2( 0, "array subscript specified incorrectly for built-in module" ); // TODO: cleanup return NULL; } // TODO: arrays? if( array_depth2 ) array_depth = array_depth2; if( array_depth ) { array_sub = new_array_sub( NULL, 0 ); for( int i = 1; i < array_depth; i++ ) array_sub = prepend_array_sub( array_sub, NULL, 0 ); } var_decl = new_var_decl( (char *)arg->name.c_str(), array_sub, 0 ); // make new arg arg_list = prepend_arg_list( type_decl, var_decl, arg_list, 0 ); } return arg_list; } //----------------------------------------------------------------------------- // name: make_dll_as_fun() // desc: make an chuck dll function into absyn function //----------------------------------------------------------------------------- a_Func_Def make_dll_as_fun( Chuck_DL_Func * dl_fun, t_CKBOOL is_static ) { a_Func_Def func_def = NULL; ae_Keyword func_decl = ae_key_func; ae_Keyword static_decl = ae_key_instance; a_Id_List type_path = NULL; a_Type_Decl type_decl = NULL; const char * name = NULL; a_Arg_List arg_list = NULL; t_CKUINT array_depth = 0; // fun decl TODO: fix this func_decl = ae_key_func; // static decl TODO: allow abstract static_decl = is_static ? ae_key_static : ae_key_instance; // path type_path = str2list( dl_fun->type, array_depth ); if( !type_path ) { // error EM_error2( 0, "...during function import '%s' (type)...", dl_fun->name.c_str() ); goto error; } // type decl // old: type_decl = new_type_decl( type_path, 1, 0 ); type_decl = new_type_decl( type_path, 0, 0 ); assert( type_decl ); if( !type_decl ) { // error EM_error2( 0, "...during function import '%s' (type2)...", dl_fun->name.c_str() ); // delete list delete_id_list( type_path ); type_path = NULL; goto error; } // array types // this allows us to define built-in functions that return array types // however doing this without garbage collection is probably a bad idea // -spencer if( array_depth ) { a_Array_Sub array_sub = new_array_sub( NULL, 0 ); for( int i = 1; i < array_depth; i++ ) array_sub = prepend_array_sub( array_sub, NULL, 0 ); type_decl = add_type_decl_array( type_decl, array_sub, 0 ); } // name of the function name = dl_fun->name.c_str(); // arg list arg_list = make_dll_arg_list( dl_fun ); if( dl_fun->args.size() > 0 && !arg_list ) { // error EM_error2( 0, "...during function import '%s' (arg_list)...", dl_fun->name.c_str() ); // delete type_decl // delete_type_decl( type_decl ); type_decl = NULL; goto error; } // make a func_def func_def = new_func_def( func_decl, static_decl, type_decl, (char *)name, arg_list, NULL, 0 ); // mark the function as imported (instead of defined in ChucK) func_def->s_type = ae_func_builtin; // copy the function pointer - the type doesn't matter here // ... since we copying into a void * - so mfun is used func_def->dl_func_ptr = (void *)dl_fun->mfun; return func_def; error: // clean up // if( !func_def ) delete_type_decl( type_decl ); // else delete_func_def( func_def ); return NULL; } //----------------------------------------------------------------------------- // name: type_engine_add_dll() // desc: add an chuck dll into the env //----------------------------------------------------------------------------- t_CKBOOL type_engine_add_dll( Chuck_Env * env, Chuck_DLL * dll, const string & dest ) { // which namespace string where = ( dest == "" ? "global" : dest ); Chuck_Namespace * nspc = NULL; const Chuck_DL_Query * query = NULL; t_CKUINT i, j; vector the_funs; // convert to id list a_Id_List path = str2list( dest ); if( !path ) goto error; // find the namespace to put the import nspc = type_engine_find_nspc( env, path ); if( !nspc ) goto error; // get the query query = dll->query(); // loop for( i = 0; i < query->classes.size(); i++ ) { a_Class_Def def = NULL; a_Class_Ext ext = NULL; a_Class_Body body = NULL; // UNUSED: a_Section sec = NULL; a_Func_Def fun = NULL; a_Id_List name; a_Id_List parent; // UNUSED: Chuck_DL_Func * dl_fun = NULL; // UNUSED: Chuck_DL_Value * dl_val = NULL; // UNUSED: Chuck_DL_Ctrl * dl_ctrl = NULL; Chuck_DL_Class * cl = query->classes[i]; assert( cl != NULL ); // get name name = str2list( cl->name ); if( !name ) goto error; // if parent is specified if( cl->parent != "" ) { // get parent parent = str2list( cl->parent ); if( !parent ) goto error; } else // if no parent specified, then extend Object { parent = str2list( "Object" ); assert( parent != NULL ); } // clear the funs vector the_funs.clear(); // loop over member functions for( j = 0; j < cl->mfuns.size(); j++ ) { // get the function from the dll fun = make_dll_as_fun( cl->mfuns[j], FALSE ); if( !fun ) goto error; // add to vector the_funs.push_back( fun ); } // loop over static functions for( j = 0; j < cl->sfuns.size(); j++ ) { // get the function from the dll fun = make_dll_as_fun( cl->sfuns[j], TRUE ); if( !fun ) goto error; // add to vector the_funs.push_back( fun ); } // loop over member data // ignored for now... -spencer for( j = 0; j < cl->mvars.size(); j++ ) { } // the next few lines take static member variables defined by the DLL // and creates a list of corresponding declarations to add to the // class definition // -spencer // static member variable declarations a_Stmt_List svar_decls = NULL; // loop over static data for( j = 0; j < cl->svars.size(); j++ ) { // get type a_Id_List path = str2list( cl->svars[j]->type.c_str() ); // make type decl a_Type_Decl type_decl = new_type_decl( path, FALSE, 0 ); // make var decl a_Var_Decl var_decl = new_var_decl( cl->svars[j]->name.c_str(), NULL, 0 ); // make var decl list a_Var_Decl_List var_decl_list = new_var_decl_list( var_decl, 0 ); // make exp decl a_Exp exp_decl = new_exp_decl( type_decl, var_decl_list, TRUE, 0 ); // add addr var_decl->addr = (void *)cl->svars[j]->static_addr; // prepend exp stmt to stmt list svar_decls = prepend_stmt_list( new_stmt_from_expression( exp_decl, 0 ), svar_decls, 0 ); } // if there are any declarations, prepend them to body if( svar_decls ) body = prepend_class_body( new_section_stmt( svar_decls, 0 ), body, 0 ); // go through funs backwards, and prepend for( t_CKINT k = (t_CKINT)the_funs.size() - 1; k >= 0; k-- ) { // add to body body = prepend_class_body( new_section_func_def( the_funs[k], 0 ), body, 0 ); } // construct class def = new_class_def( ae_key_public, name, ext, body, 0 ); // set where to add def->home = nspc; // TODO: mark the class as dll import? // scan type check it if( !type_engine_scan0_class_def( env, def ) ) goto error; if( !type_engine_scan1_class_def( env, def ) ) goto error; if( !type_engine_scan2_class_def( env, def ) ) goto error; if( !type_engine_check_class_def( env, def ) ) goto error; // TODO: clean up? } // free the path delete_id_list( path ); return TRUE; error: // error EM_error2( 0, "...(in object import '%s' in DLL '%s')", query ? ( query->dll_name.c_str() == "" ? query->dll_name.c_str() : "[empty]" ) : "[null]", dll->name() ); // free the path delete_id_list( path ); // TODO: free the absyn stuff? return FALSE; } static const char * g_howmuch[] = { "ALL", "CLASSES_ONLY", "ALL_EXCEPT_CLASSES" }; //----------------------------------------------------------------------------- // name: howmuch2str() // desc: ... //----------------------------------------------------------------------------- const char * howmuch2str( te_HowMuch how_much ) { if( how_much < 0 || how_much > te_do_no_classes ) return "[INVALID]"; else return g_howmuch[how_much]; } // table of escape characters static char g_escape[256]; static t_CKBOOL g_escape_ready = FALSE; //----------------------------------------------------------------------------- // name: escape_table() // desc: ... //----------------------------------------------------------------------------- void escape_table( ) { // escape g_escape['\''] = '\''; g_escape['"'] = '"'; g_escape['\\'] = '\\'; g_escape['a'] = (char)7; // audible bell g_escape['b'] = (char)8; // back space g_escape['f'] = (char)12; // form feed g_escape['n'] = (char)10; // new line g_escape['r'] = (char)13; // carriage return g_escape['t'] = (char)9; // horizontal tab g_escape['v'] = (char)11; // vertical tab // done g_escape_ready = TRUE; } //----------------------------------------------------------------------------- // name: escape_str() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL escape_str( char * str_lit, int linepos ) { // create if not yet if( !g_escape_ready ) escape_table( ); // write pointer char * str = str_lit; // unsigned because we index array of 256 unsigned char c, c2, c3; // iterate while( *str_lit ) { // if \ encountered if( *str_lit == '\\' ) { // advance pointer str_lit++; // make sure next char if( *str_lit == '\0' ) { EM_error2( linepos, "invalid: string ends with escape charactor '\\'" ); return FALSE; } // next characters c = *(str_lit); c2 = *(str_lit+1); // is octal? if( c >= '0' && c <= '7' ) { // look at next if( c == '0' && ( c2 < '0' || c2 > '7' ) ) *str++ = '\0'; else { // get next c3 = *(str_lit+2); // all three should be within range if( c2 >= '0' && c2 <= '7' && c3 >= '0' && c3 <= '7' ) { // ascii value *str++ = (c-'0') * 64 + (c2-'0') * 8 + (c3-'0'); // advance pointer str_lit += 2; } else { EM_error2( linepos, "malformed octal escape sequence '\\%c%c%c'", c, c2, c3 ); return FALSE; } } } else if( c == 'x' ) // is hex? { EM_error2( linepos, "hex escape sequence not (yet) supported (use octal!)"); return FALSE; } else // is other? { // lookup if( g_escape[(int)c] ) *str++ = g_escape[c]; else // error { EM_error2( linepos, "unrecognized escape sequence '\\%c'", c ); return FALSE; } } } else { // char *str++ = *str_lit; } // advance pointer str_lit++; } // make sure assert( str <= str_lit ); // terminate *str = '\0'; return TRUE; } chuck-1.2.0.8.dfsg/src/chuck_type.h0000644000175000017500000006230310600421721015440 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_type.h // desc: chuck type-system / type-checker // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 - original // Autumn 2004 - rewrite //----------------------------------------------------------------------------- #ifndef __CHUCK_TYPE_H__ #define __CHUCK_TYPE_H__ #include "chuck_def.h" #include "chuck_absyn.h" #include "chuck_oo.h" #include "chuck_dl.h" #include "chuck_errmsg.h" //----------------------------------------------------------------------------- // name: enum te_Type // desc: basic, default ChucK types //----------------------------------------------------------------------------- typedef enum { // general types te_int, te_uint, te_single, te_float, te_double, te_time, te_dur, te_string, te_thread, te_shred, te_class, te_function, te_object, te_user, te_array, te_null, te_ugen, te_event, te_void, te_stdout, te_stderr, te_adc, te_dac, te_bunghole, te_midiin, te_midiout, te_multi } te_Type; //----------------------------------------------------------------------------- // name: enum te_HowMuch // desc: how much to scan/type check //----------------------------------------------------------------------------- typedef enum { te_do_all = 0, te_do_classes_only, te_do_no_classes } te_HowMuch; //----------------------------------------------------------------------------- // name: struct Chuck_Scope // desc: scoping structure //----------------------------------------------------------------------------- template struct Chuck_Scope { public: // constructor Chuck_Scope() { this->push(); } // desctructor ~Chuck_Scope() { this->pop(); } // push scope void push() { scope.push_back( new std::map ); } // pop scope void pop() { assert( scope.size() != 0 ); // TODO: release contents of scope.back() delete scope.back(); scope.pop_back(); } // reset the scope void reset() { scope.clear(); this->push(); } // atomic commit void commit() { assert( scope.size() != 0 ); std::map::iterator iter; // go through buffer for( iter = commit_map.begin(); iter != commit_map.end(); iter++ ) { // add to front/where (*scope.front())[(*iter).first] = (*iter).second; } // clear commit_map.clear(); } // roll back since last commit or beginning void rollback() { assert( scope.size() != 0 ); std::map::iterator iter; // go through buffer for( iter = commit_map.begin(); iter != commit_map.end(); iter++ ) { // release (*iter).second->release(); } // clear commit_map.clear(); } // add void add( const std::string & xid, Chuck_VM_Object * value ) { this->add( insert_symbol(xid.c_str()), value ); } void add( S_Symbol xid, Chuck_VM_Object * value ) { assert( scope.size() != 0 ); // add if back is NOT front if( scope.back() != scope.front() ) (*scope.back())[xid] = value; // add for commit else commit_map[xid] = value; // add reference SAFE_ADD_REF(value); } // lookup id T operator []( const std::string & xid ) { return (T)this->lookup( xid ); } T lookup( const std::string & xid, t_CKINT climb = 1 ) { return (T)this->lookup( insert_symbol(xid.c_str()), climb ); } // -1 base, 0 current, 1 climb T lookup( S_Symbol xid, t_CKINT climb = 1 ) { Chuck_VM_Object * val = NULL; assert( scope.size() != 0 ); if( climb == 0 ) { val = (*scope.back())[xid]; // look in commit buffer if the back is the front if( !val && scope.back() == scope.front() && (commit_map.find(xid) != commit_map.end()) ) val = commit_map[xid]; } else if( climb > 0 ) { for( t_CKUINT i = scope.size(); i > 0; i-- ) { if( val = (*scope[i-1])[xid] ) break; } // look in commit buffer if( !val && (commit_map.find(xid) != commit_map.end()) ) val = commit_map[xid]; } else { val = (*scope.front())[xid]; // look in commit buffer if( !val && (commit_map.find(xid) != commit_map.end()) ) val = commit_map[xid]; } return (T)val; } // get list of top level void get_toplevel( std::vector & out ) { assert( scope.size() != 0 ); std::map::iterator iter; // clear the out out.clear(); // get the front of the array std::map * m = scope.front(); // go through map for( iter = m->begin(); iter != m->end(); iter++ ) { // add out.push_back( (*iter).second ); } } protected: std::vector *> scope; std::map commit_map; }; // forward reference struct Chuck_Type; struct Chuck_Value; struct Chuck_Func; struct Chuck_Multi; struct Chuck_VM; struct Chuck_VM_Code; struct Chuck_DLL; //----------------------------------------------------------------------------- // name: struct Chuck_Namespace // desc: Chuck Namespace containing semantic information //----------------------------------------------------------------------------- struct Chuck_Namespace : public Chuck_VM_Object { // maps Chuck_Scope type; Chuck_Scope value; Chuck_Scope func; // virtual table Chuck_VTable obj_v_table; // static data segment t_CKBYTE * class_data; // static data segment size t_CKUINT class_data_size; // name std::string name; // top-level code Chuck_VM_Code * pre_ctor; // destructor Chuck_VM_Code * dtor; // type that contains this Chuck_Namespace * parent; // address offset t_CKUINT offset; // constructor Chuck_Namespace() { pre_ctor = NULL; dtor = NULL; parent = NULL; offset = 0; class_data = NULL; class_data_size = 0; } // destructor virtual ~Chuck_Namespace() { /* TODO: SAFE_RELEASE( this->parent ); */ /* TODO: SAFE_DELETE( pre_ctor ); */ /* TODO: SAFE_DELETE( dtor ); */ } // look up type Chuck_Type * lookup_type( const std::string & name, t_CKINT climb = 1 ); Chuck_Type * lookup_type( S_Symbol name, t_CKINT climb = 1 ); // look up value Chuck_Value * lookup_value( const std::string & name, t_CKINT climb = 1 ); Chuck_Value * lookup_value( S_Symbol name, t_CKINT climb = 1 ); // look up func Chuck_Func * lookup_func( const std::string & name, t_CKINT climb = 1 ); Chuck_Func * lookup_func( S_Symbol name, t_CKINT climb = 1 ); // commit the maps void commit() { EM_log( CK_LOG_FINER, "committing namespace: '%s'...", name.c_str() ); type.commit(); value.commit(); func.commit(); } // rollback the maps void rollback() { EM_log( CK_LOG_FINER, "rolling back namespace: '%s'...", name.c_str() ); type.rollback(); value.rollback(); func.rollback(); } // get top level types void get_types( std::vector & out ); // get top level values void get_values( std::vector & out ); // get top level functions void get_funcs( std::vector & out ); }; //----------------------------------------------------------------------------- // name: struct Chuck_Context // desc: runtime type information pertaining to a file //----------------------------------------------------------------------------- struct Chuck_Context : public Chuck_VM_Object { // src_name std::string filename; // parse tree a_Program parse_tree; // context namespace Chuck_Namespace * nspc; // public class def if any a_Class_Def public_class_def; // error - means to free nspc too t_CKBOOL has_error; // progress enum { P_NONE = 0, P_CLASSES_ONLY, P_ALL }; // progress in scan / type check / emit t_CKUINT progress; // things to release with the context std::vector new_types; std::vector new_values; std::vector new_funcs; std::vector new_nspc; // commit map std::map commit_map; // add for commit/rollback void add_commit_candidate( Chuck_Namespace * nspc ); // commit void commit(); // rollback void rollback(); // constructor Chuck_Context() { parse_tree = NULL; nspc = new Chuck_Namespace; public_class_def = NULL; has_error = FALSE; progress = P_NONE; } // destructor virtual ~Chuck_Context(); // get the top-level code Chuck_VM_Code * code() { return nspc->pre_ctor; } // special alloc Chuck_Type * new_Chuck_Type(); Chuck_Value * new_Chuck_Value( Chuck_Type * t, const std::string & name ); Chuck_Func * new_Chuck_Func(); Chuck_Namespace * new_Chuck_Namespace(); }; //----------------------------------------------------------------------------- // name: struct Chuck_Env // desc: chuck env with type info //----------------------------------------------------------------------------- struct Chuck_Env : public Chuck_VM_Object { public: static t_CKBOOL startup(); static Chuck_Env * instance(); static t_CKBOOL shutdown(); private: static Chuck_Env * our_instance; // constructor Chuck_Env( ) { // lock from being deleted global_context.lock(); // make reference context = &global_context; SAFE_ADD_REF(context); // make name context->filename = "@[global]"; // remember global_nspc = global_context.nspc; SAFE_ADD_REF(global_nspc); // deprecated stuff deprecated.clear(); deprecate_level = 1; // clear this->reset(); } protected: // global namespace Chuck_Namespace * global_nspc; // global context Chuck_Context global_context; public: // global namespace Chuck_Namespace * global() { return global_nspc; } // namespace stack std::vector nspc_stack; // expression namespace Chuck_Namespace * curr; // class stack std::vector class_stack; // current class definition Chuck_Type * class_def; // current function definition Chuck_Func * func; // how far nested in a class definition t_CKUINT class_scope; // current contexts in memory std::vector contexts; // current context Chuck_Context * context; // control scope (for break, continue) std::vector breaks; // reserved words std::map key_words; std::map key_types; std::map key_values; // deprecated types std::map deprecated; // level - 0:stop, 1:warn, 2:ignore t_CKINT deprecate_level; // destructor virtual ~Chuck_Env() { } // reset void reset( ) { // TODO: release stack items? nspc_stack.clear(); nspc_stack.push_back( this->global() ); // TODO: release stack items? class_stack.clear(); class_stack.push_back( NULL ); // should be at top level assert( context == &global_context ); // assign : TODO: release curr? class_def? func? // TODO: need another function, since this is called from constructor curr = this->global(); class_def = NULL; func = NULL; // make sure this is 0 class_scope = 0; } // top Chuck_Namespace * nspc_top( ) { assert( nspc_stack.size() > 0 ); return nspc_stack.back(); } Chuck_Type * class_top( ) { assert( class_stack.size() > 0 ); return class_stack.back(); } }; //----------------------------------------------------------------------------- // name: struct Chuck_UGen_Info // desc: ugen info stored with ugen types //----------------------------------------------------------------------------- struct Chuck_UGen_Info : public Chuck_VM_Object { // tick function pointer f_tick tick; // pmsg function pointer f_pmsg pmsg; // number of incoming channels t_CKUINT num_ins; // number of outgoing channels t_CKUINT num_outs; // constructor Chuck_UGen_Info() { tick = NULL; pmsg = NULL; num_ins = 1; num_outs = 1; } }; //----------------------------------------------------------------------------- // name: struct Chuck_Type // desc: class containing information about a type //-----------------------------------------------------------------------------_id struct Chuck_Type : public Chuck_VM_Object { // type id te_Type xid; // type name std::string name; // type parent (could be NULL) Chuck_Type * parent; // size (in bytes) t_CKUINT size; // owner of the type Chuck_Namespace * owner; // array type union { Chuck_Type * array_type; Chuck_Type * actual_type; }; // array size (equals 0 means not array, else dimension of array) t_CKUINT array_depth; // object size (size in memory) t_CKUINT obj_size; // type info Chuck_Namespace * info; // func info Chuck_Func * func; // def a_Class_Def def; // ugen Chuck_UGen_Info * ugen_info; // copy t_CKBOOL is_copy; // defined t_CKBOOL is_complete; // has pre constructor t_CKBOOL has_constructor; // has destructor t_CKBOOL has_destructor; public: // constructor Chuck_Type( te_Type _id = te_null, const std::string & _n = "", Chuck_Type * _p = NULL, t_CKUINT _s = 0 ) { xid = _id; name = _n; parent = _p; size = _s; owner = NULL; array_type = NULL; array_depth = 0; obj_size = 0; info = NULL; func = NULL; def = NULL; is_copy = FALSE; ugen_info = NULL; is_complete = TRUE; has_constructor = FALSE; has_destructor = FALSE; } // destructor virtual ~Chuck_Type() { reset(); } // reset void reset() { // fprintf( stderr, "type: %s %i\n", c_name(), (t_CKUINT)this ); xid = te_void; size = array_depth = obj_size = 0; is_copy = FALSE; // free only if not locked: to prevent garbage collection after exit if( !this->m_locked ) { // release references // SAFE_RELEASE(parent); // SAFE_RELEASE(array_type); SAFE_RELEASE(info); // SAFE_RELEASE(owner); // SAFE_RELEASE(func); // SAFE_RELEASE(ugen_info); } } // assignment - this does not touch the Chuck_VM_Object const Chuck_Type & operator =( const Chuck_Type & rhs ) { // release first this->reset(); // copy this->xid = rhs.xid; this->name = rhs.name; this->parent = rhs.parent; this->obj_size = rhs.obj_size; this->size = rhs.size; this->def = rhs.def; this->is_copy = TRUE; this->array_depth = rhs.array_depth; this->array_type = rhs.array_type; // SAFE_ADD_REF(this->array_type); this->func = rhs.func; // SAFE_ADD_REF(this->func); this->info = rhs.info; SAFE_ADD_REF(this->info); this->owner = rhs.owner; // SAFE_ADD_REF(this->owner); return *this; } // copy Chuck_Type * copy( Chuck_Env * env ) const { Chuck_Type * n = env->context->new_Chuck_Type(); *n = *this; return n; } // to string std::string ret; const std::string & str() { ret = name; for( t_CKUINT i = 0; i < array_depth; i++ ) ret += std::string("[]"); return ret; } // to c const char * c_name() { return str().c_str(); } }; //----------------------------------------------------------------------------- // name: struct Chuck_Value // desc: a variable in scope //----------------------------------------------------------------------------- struct Chuck_Value : public Chuck_VM_Object { // type Chuck_Type * type; // name std::string name; // offset t_CKUINT offset; // addr void * addr; // const? t_CKBOOL is_const; // member? t_CKBOOL is_member; // static? t_CKBOOL is_static; // do something // is context-global? t_CKBOOL is_context_global; // is decl checked t_CKBOOL is_decl_checked; // 0 = public, 1 = protected, 2 = private t_CKUINT access; // owner Chuck_Namespace * owner; // owner (class) Chuck_Type * owner_class; // remember function pointer - if this is a function Chuck_Func * func_ref; // overloads t_CKINT func_num_overloads; // constructor Chuck_Value( Chuck_Type * t, const std::string & n, void * a = NULL, t_CKBOOL c = FALSE, t_CKBOOL acc = 0, Chuck_Namespace * o = NULL, Chuck_Type * oc = NULL, t_CKUINT s = 0 ) { type = t; SAFE_ADD_REF(type); // add reference name = n; offset = s; is_const = c; access = acc; owner = o; SAFE_ADD_REF(o); // add reference owner_class = oc; SAFE_ADD_REF(oc); // add reference addr = a; is_member = FALSE; is_static = FALSE; is_context_global = FALSE; is_decl_checked = TRUE; // only set to false in certain cases func_ref = NULL; func_num_overloads = 0; } // destructor virtual ~Chuck_Value() { // release // SAFE_RELEASE( type ); // SAFE_RELEASE( owner ): // SAFE_RELEASE( owner_class ); // SAFE_RELEASE( func_ref ); } }; //----------------------------------------------------------------------------- // name: struct Chuck_Func // desc: function definition //----------------------------------------------------------------------------- struct Chuck_Func : public Chuck_VM_Object { // name std::string name; // func def from parser a_Func_Def def; // code Chuck_VM_Code * code; // imported code Chuck_DL_Func * dl_code; // member t_CKBOOL is_member; // virtual table index t_CKUINT vt_index; // rember value Chuck_Value * value_ref; // for overloading Chuck_Func * next; // for overriding Chuck_Value * up; // constructor Chuck_Func() { def = NULL; code = NULL; is_member = FALSE; vt_index = 0xffffffff; value_ref = NULL; dl_code = NULL; next = NULL; up = NULL; } // destructor virtual ~Chuck_Func() { } }; //----------------------------------------------------------------------------- // primary chuck type checker interface //----------------------------------------------------------------------------- // initialize the type engine Chuck_Env * type_engine_init( Chuck_VM * vm ); // shutdown the type engine void type_engine_shutdown( Chuck_Env * env ); // load a context to be type-checked or emitted t_CKBOOL type_engine_load_context( Chuck_Env * env, Chuck_Context * context ); // unload a context after being emitted t_CKBOOL type_engine_unload_context( Chuck_Env * env ); // type check a program into the env t_CKBOOL type_engine_check_prog( Chuck_Env * env, a_Program prog, const std::string & filename ); // make a context Chuck_Context * type_engine_make_context( a_Program prog, const std::string & filename ); // type check a context into the env t_CKBOOL type_engine_check_context( Chuck_Env * env, Chuck_Context * context, te_HowMuch how_much = te_do_all ); // type check a statement t_CKBOOL type_engine_check_stmt( Chuck_Env * env, a_Stmt stmt ); // type check an expression t_CKTYPE type_engine_check_exp( Chuck_Env * env, a_Exp exp ); // add an chuck dll into the env t_CKBOOL type_engine_add_dll( Chuck_Env * env, Chuck_DLL * dll, const std::string & nspc ); // type equality t_CKBOOL operator ==( const Chuck_Type & lhs, const Chuck_Type & rhs ); t_CKBOOL operator !=( const Chuck_Type & lhs, const Chuck_Type & rhs ); t_CKBOOL equals( Chuck_Type * lhs, Chuck_Type * rhs ); t_CKBOOL operator <=( const Chuck_Type & lhs, const Chuck_Type & rhs ); t_CKBOOL isa( Chuck_Type * lhs, Chuck_Type * rhs ); t_CKBOOL isprim( Chuck_Type * type ); t_CKBOOL isobj( Chuck_Type * type ); t_CKBOOL isfunc( Chuck_Type * type ); // import Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, Chuck_Type * type, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor = NULL ); Chuck_Type * type_engine_import_class_begin( Chuck_Env * env, const char * name, const char * parent, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor = NULL ); Chuck_Type * type_engine_import_ugen_begin( Chuck_Env * env, const char * name, const char * parent, Chuck_Namespace * where, f_ctor pre_ctor, f_dtor dtor, f_tick tick, f_pmsg pmsg, t_CKUINT num_ins = 0xffffffff, t_CKUINT num_outs = 0xffffffff ); t_CKBOOL type_engine_import_mfun( Chuck_Env * env, Chuck_DL_Func * mfun ); t_CKBOOL type_engine_import_sfun( Chuck_Env * env, Chuck_DL_Func * sfun ); t_CKUINT type_engine_import_mvar( Chuck_Env * env, const char * type, const char * name, t_CKUINT is_const ); t_CKBOOL type_engine_import_svar( Chuck_Env * env, const char * type, const char * name, t_CKUINT is_const, t_CKUINT addr ); t_CKBOOL type_engine_import_ugen_ctrl( Chuck_Env * env, const char * type, const char * name, f_ctrl ctrl, t_CKBOOL write, t_CKBOOL read ); t_CKBOOL type_engine_import_class_end( Chuck_Env * env ); t_CKBOOL type_engine_register_deprecate( Chuck_Env * env, const std::string & former, const std::string & latter ); // helpers t_CKBOOL type_engine_check_reserved( Chuck_Env * env, const std::string & xid, int pos ); t_CKBOOL type_engine_check_reserved( Chuck_Env * env, S_Symbol xid, int pos ); t_CKBOOL type_engine_check_primitive( Chuck_Type * type ); t_CKBOOL type_engine_compat_func( a_Func_Def lhs, a_Func_Def rhs, int pos, std::string & err, t_CKBOOL print = TRUE ); t_CKBOOL type_engine_get_deprecate( Chuck_Env * env, const std::string & from, std::string & to ); Chuck_Type * type_engine_find_common_anc( Chuck_Type * lhs, Chuck_Type * rhs ); Chuck_Type * type_engine_find_type( Chuck_Env * env, a_Id_List path ); Chuck_Value * type_engine_find_value( Chuck_Type * type, const std::string & xid ); Chuck_Value * type_engine_find_value( Chuck_Type * type, S_Symbol xid ); Chuck_Value * type_engine_find_value( Chuck_Env * env, const std::string & xid, t_CKBOOL climb, int linepos = 0 ); Chuck_Namespace * type_engine_find_nspc( Chuck_Env * env, a_Id_List path ); // array verify t_CKBOOL verify_array( a_Array_Sub array ); // make array type Chuck_Type * new_array_type( Chuck_Env * env, Chuck_Type * array_parent, t_CKUINT depth, Chuck_Type * base_type, Chuck_Namespace * owner_nspc ); // conversion const char * type_path( a_Id_List path ); a_Id_List str2list( const std::string & path ); a_Id_List str2list( const std::string & path, t_CKBOOL & is_array ); const char * howmuch2str( te_HowMuch how_much ); t_CKBOOL escape_str( char * str_lit, int linepos ); // default types extern Chuck_Type t_void; extern Chuck_Type t_int; extern Chuck_Type t_float; extern Chuck_Type t_time; extern Chuck_Type t_dur; extern Chuck_Type t_object; extern Chuck_Type t_null; extern Chuck_Type t_string; extern Chuck_Type t_array; extern Chuck_Type t_shred; extern Chuck_Type t_thread; extern Chuck_Type t_function; extern Chuck_Type t_class; extern Chuck_Type t_event; extern Chuck_Type t_ugen; #endif chuck-1.2.0.8.dfsg/src/chuck_ugen.cpp0000644000175000017500000004011510600421721015745 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_ugen.cpp // desc: chuck unit generator interface // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2004 - 1.1 // spring 2005 - 1.2 //----------------------------------------------------------------------------- #include "chuck_ugen.h" #include "chuck_vm.h" #include "chuck_errmsg.h" using namespace std; //----------------------------------------------------------------------------- // fast array //----------------------------------------------------------------------------- void fa_init( Chuck_UGen ** & base, t_CKUINT & capacity ); void fa_done( Chuck_UGen ** & base, t_CKUINT & capacity ); void fa_resize( Chuck_UGen ** & base, t_CKUINT & capacity ); void fa_push_back( Chuck_UGen ** & base, t_CKUINT & capacity, t_CKUINT size, Chuck_UGen * value ); t_CKBOOL fa_lookup( Chuck_UGen ** base, t_CKUINT size, const Chuck_UGen * value ); //----------------------------------------------------------------------------- // name: fa_init() // desc: ... //----------------------------------------------------------------------------- void fa_init( Chuck_UGen ** & base, t_CKUINT & capacity ) { base = NULL; capacity = 0; } //----------------------------------------------------------------------------- // name: fa_done() // desc: ... //----------------------------------------------------------------------------- void fa_done( Chuck_UGen ** & base, t_CKUINT & capacity ) { if( base ) delete [] base; base = NULL; capacity = 0; } //----------------------------------------------------------------------------- // name: fa_resize() // desc: ... //----------------------------------------------------------------------------- void fa_resize( Chuck_UGen ** & base, t_CKUINT & capacity ) { // initial if( capacity == 0 ) capacity = 8; else capacity *= 2; // allocate Chuck_UGen ** new_base = new Chuck_UGen *[capacity]; // delete if( base ) { // copy memcpy( new_base, base, capacity / 2 * sizeof(Chuck_UGen *) ); // delete delete [] base; } // done base = new_base; } //----------------------------------------------------------------------------- // name: fa_push_back() // desc: ... //----------------------------------------------------------------------------- void fa_push_back( Chuck_UGen ** & base, t_CKUINT & capacity, t_CKUINT size, Chuck_UGen * value ) { // resize if( size == capacity ) fa_resize( base, capacity ); // add base[size] = value; } //----------------------------------------------------------------------------- // name: fa_lookup() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL fa_lookup( Chuck_UGen ** base, t_CKUINT size, const Chuck_UGen * value ) { // loop for( t_CKUINT i = 0; i < size; i++ ) if( base[i] == value ) return TRUE; // not found return FALSE; } //----------------------------------------------------------------------------- // name: Chuck_UGen() // desc: constructor //----------------------------------------------------------------------------- Chuck_UGen::Chuck_UGen() { this->init(); } //----------------------------------------------------------------------------- // name: ~Chuck_UGen() // desc: ... //----------------------------------------------------------------------------- Chuck_UGen::~Chuck_UGen() { this->done(); } //----------------------------------------------------------------------------- // name: init() // desc: ... //----------------------------------------------------------------------------- void Chuck_UGen::init() { tick = NULL; pmsg = NULL; m_multi_chan = NULL; m_multi_chan_size = 0; m_num_ins = 1; m_num_outs = 1; fa_init( m_src_list, m_src_cap ); fa_init( m_dest_list, m_dest_cap ); m_num_src = 0; m_num_dest = 0; m_max_src = 0xffffffff; m_time = 0; m_valid = TRUE; m_sum = 0.0f; m_current = 0.0f; m_last = 0.0f; m_op = UGEN_OP_TICK; m_gain = 1.0f; m_pan = 1.0f; m_next = 0.0f; m_use_next = FALSE; shred = NULL; owner = NULL; } //----------------------------------------------------------------------------- // name: done() // desc: ... //----------------------------------------------------------------------------- void Chuck_UGen::done() { if( this->shred ) shred->remove( this ); assert( this->m_ref_count == 0 ); // disconnect this->disconnect( TRUE ); m_valid = FALSE; fa_done( m_src_list, m_src_cap ); fa_done( m_dest_list, m_dest_cap ); // TODO: m_multi_chan, break ref count loop } //----------------------------------------------------------------------------- // name: alloc_multi_chan() // desc: ... //----------------------------------------------------------------------------- void Chuck_UGen::alloc_multi_chan( t_CKUINT num_ins, t_CKUINT num_outs ) { // get max of num_ins and num_outs m_multi_chan_size = ( num_ins > num_outs ? num_ins : num_outs ); // allocate m_multi_chan = new Chuck_UGen *[m_multi_chan_size]; // zero it out, whoever call this will fill in memset( m_multi_chan, 0, m_multi_chan_size * sizeof(Chuck_UGen *) ); // mono if( m_multi_chan_size == 1 ) { // zero out m_multi_chan_size = 0; // self m_multi_chan[0] = this; } // remember m_num_ins = num_ins; m_num_outs = num_outs; } //----------------------------------------------------------------------------- // name: set_max_src() // dsec: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::set_max_src( t_CKUINT num ) { m_max_src = num; return TRUE; } //----------------------------------------------------------------------------- // name: get_num_src() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_UGen::get_num_src() { return m_num_src; } //----------------------------------------------------------------------------- // name: add() // dsec: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::add( Chuck_UGen * src ) { // examine ins and outs t_CKUINT outs = src->m_num_outs; t_CKUINT ins = this->m_num_ins; t_CKUINT i; if( outs == 1 && ins == 1 ) { // check if already connected if( fa_lookup( m_src_list, m_num_src, src ) ) return FALSE; // check for limit if( m_num_src >= m_max_src ) return FALSE; // append fa_push_back( m_src_list, m_src_cap, m_num_src, src ); m_num_src++; src->add_ref(); src->add_by( this ); } else if( outs >= 2 && ins == 1 ) { // check if already connect if( fa_lookup( m_src_list, m_num_src, src ) ) return FALSE; // check for limit if( m_num_src >= m_max_src ) return FALSE; // append fa_push_back( m_src_list, m_src_cap, m_num_src, src ); m_num_src++; src->add_ref(); src->add_by( this ); } else if( outs == 1 && ins >= 2 ) { // add to each channel for( i = 0; i < ins; i++ ) if( !this->m_multi_chan[i]->add( src ) ) return FALSE; } else if( outs >= 2 && ins >= 2 ) { // add to each channel for( i = 0; i < ins; i++ ) if( !this->m_multi_chan[i]->add( src->m_multi_chan[i%outs] ) ) return FALSE; } else { EM_error3( "internal error: unhandled UGen add: outs: %d ins: %d", outs, ins ); assert( FALSE ); } return TRUE; } //----------------------------------------------------------------------------- // name: add_by() // dsec: ... //----------------------------------------------------------------------------- void Chuck_UGen::add_by( Chuck_UGen * dest ) { // append fa_push_back( m_dest_list, m_dest_cap, m_num_dest, dest ); dest->add_ref(); m_num_dest++; } //----------------------------------------------------------------------------- // name: remove() // dsec: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::remove( Chuck_UGen * src ) { // ins and outs t_CKUINT outs = src->m_num_outs; t_CKUINT ins = this->m_num_ins; t_CKUINT i; t_CKBOOL ret = FALSE; // take action if( outs == 1 && ins == 1 ) { if( m_num_src == 0 ) return FALSE; // remove for( unsigned int i = 0; i < m_num_src; i++ ) if( m_src_list[i] == src ) { ret = TRUE; for( unsigned int j = i+1; j < m_num_src; j++ ) m_src_list[j-1] = m_src_list[j]; m_src_list[--m_num_src] = NULL; src->remove_by( this ); src->release(); } } else if( outs >= 2 && ins == 1 ) { if( m_num_src == 0 ) return FALSE; // remove for( unsigned int i = 0; i < m_num_src; i++ ) if( m_src_list[i] == src ) { ret = TRUE; for( unsigned int j = i+1; j < m_num_src; j++ ) m_src_list[j-1] = m_src_list[j]; m_src_list[--m_num_src] = NULL; src->remove_by( this ); src->release(); } } else if( outs == 1 && ins >= 2 ) { for( i = 0; i < ins; i++ ) if( !m_multi_chan[i]->remove( src ) ) return FALSE; ret = TRUE; } else if( outs >= 2 && ins >= 2 ) { for( i = 0; i < ins; i++ ) if( !m_multi_chan[i]->remove( src->m_multi_chan[i%outs] ) ) return FALSE; ret = TRUE; } return ret; } //----------------------------------------------------------------------------- // name: remove_by() // dsec: ... //----------------------------------------------------------------------------- void Chuck_UGen::remove_by( Chuck_UGen * dest ) { // remove for( unsigned int i = 0; i < m_num_dest; i++ ) if( m_dest_list[i] == dest ) { // get rid of it for( unsigned int j = i+1; j < m_num_dest; j++ ) m_dest_list[j-1] = m_dest_list[j]; // release dest->release(); // null the last element m_dest_list[--m_num_dest] = NULL; } } //----------------------------------------------------------------------------- // name: add() // dsec: ... //----------------------------------------------------------------------------- void Chuck_UGen::remove_all( ) { assert( this->m_num_dest == 0 ); // remove while( m_num_src > 0 ) { // make sure at least one got disconnected if( !this->remove( m_src_list[0] ) ) { // get rid of it, but don't release for( unsigned int j = 1; j < m_num_src; j++ ) m_src_list[j-1] = m_src_list[j]; // null the last element m_src_list[--m_num_src] = NULL; } } } //----------------------------------------------------------------------------- // name: disconnect() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::disconnect( t_CKBOOL recursive ) { // remove while( m_num_dest > 0 ) { // make sure at least one got disconnected if( !m_dest_list[0]->remove( this ) ) { // get rid of it, but don't release for( unsigned int j = 1; j < m_num_dest; j++ ) m_dest_list[j-1] = m_dest_list[j]; // null the last element m_dest_list[--m_num_dest] = NULL; } } // for( unsigned int i = 0; i < m_num_dest; i++ ) // m_dest_list[i]->remove( this ); // m_num_dest = 0; // disconnect src too? if( recursive ) this->remove_all(); return TRUE; } //----------------------------------------------------------------------------- // name: is_connected_from() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::is_connected_from( Chuck_UGen * src ) { if( m_src_list != NULL && fa_lookup( m_src_list, m_num_src, src ) ) return TRUE; // multichannel if( m_multi_chan != NULL ) { for( t_CKUINT i = 0; i < m_multi_chan_size; i++ ) { if( fa_lookup( m_multi_chan[i]->m_src_list, m_multi_chan[i]->m_num_src, src ) ) return TRUE; } } return FALSE; } //----------------------------------------------------------------------------- // name: tick() // dsec: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_UGen::system_tick( t_CKTIME now ) { if( m_time >= now ) return m_valid; t_CKUINT i; Chuck_UGen * ugen; SAMPLE multi; // inc time m_time = now; // initial sum m_sum = 0.0f; if( m_num_src ) { ugen = m_src_list[0]; if( ugen->m_time < now ) ugen->system_tick( now ); m_sum = ugen->m_current; // tick the src list for( i = 1; i < m_num_src; i++ ) { ugen = m_src_list[i]; if( ugen->m_time < now ) ugen->system_tick( now ); if( ugen->m_valid ) { if( m_op <= 1 ) m_sum += ugen->m_current; else // special ops { switch( m_op ) { case 2: m_sum -= ugen->m_current; break; case 3: m_sum *= ugen->m_current; break; case 4: m_sum /= ugen->m_current; break; default: m_sum += ugen->m_current; break; } } } } } // tick multiple channels multi = 0.0f; if( m_multi_chan_size ) { for( i = 0; i < m_multi_chan_size; i++ ) { ugen = m_multi_chan[i]; if( ugen->m_time < now ) ugen->system_tick( now ); // multiple channels are added multi += ugen->m_current; } // scale multi multi /= m_multi_chan_size; m_sum += multi; } // if owner if( owner != NULL && owner->m_time < now ) owner->system_tick( now ); if( m_op > 0 ) // UGEN_OP_TICK { // tick the ugen if( tick ) m_valid = tick( this, m_sum, &m_current, NULL ); if( !m_valid ) m_current = 0.0f; m_current *= m_gain * m_pan; m_last = m_current; return m_valid; } else if( m_op < 0 ) // UGEN_OP_PASS { // pass through m_current = m_sum; m_last = m_current; return TRUE; } else // UGEN_OP_STOP m_current = 0.0f; m_last = m_current; return TRUE; } chuck-1.2.0.8.dfsg/src/chuck_ugen.h0000644000175000017500000000665010600421721015420 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: chuck_ugen.h // desc: chuck unit generator interface // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2004 - 1.1 // spring 2005 - 1.2 //----------------------------------------------------------------------------- #ifndef __CHUCK_UGEN_H__ #define __CHUCK_UGEN_H__ #include "chuck_def.h" #include "chuck_oo.h" #include "chuck_dl.h" // forward reference struct Chuck_VM_Shred; // op mode #define UGEN_OP_PASS -1 #define UGEN_OP_STOP 0 #define UGEN_OP_TICK 1 //----------------------------------------------------------------------------- // name: struct Chuck_UGen // dsec: ugen base //----------------------------------------------------------------------------- struct Chuck_UGen : public Chuck_Object { public: Chuck_UGen( ); virtual ~Chuck_UGen( ); virtual void init(); virtual void done(); public: // src t_CKBOOL add( Chuck_UGen * src ); t_CKBOOL remove( Chuck_UGen * src ); t_CKVOID remove_all( ); t_CKBOOL set_max_src( t_CKUINT num ); t_CKUINT get_num_src( ); t_CKBOOL is_connected_from( Chuck_UGen * src ); t_CKUINT disconnect( t_CKBOOL recursive ); t_CKUINT system_tick( t_CKTIME now ); protected: t_CKVOID add_by( Chuck_UGen * dest ); t_CKVOID remove_by( Chuck_UGen * dest ); public: // tick function f_tick tick; // msg function f_pmsg pmsg; // channels (if more than one is required) Chuck_UGen ** m_multi_chan; // size of m_multi_chan; t_CKUINT m_multi_chan_size; // number of channels t_CKUINT m_num_ins; // number of channels t_CKUINT m_num_outs; // alloc multi channels void alloc_multi_chan( t_CKUINT num_ins, t_CKUINT num_outs ); public: // data Chuck_UGen ** m_src_list; t_CKUINT m_src_cap; t_CKUINT m_num_src; Chuck_UGen ** m_dest_list; t_CKUINT m_dest_cap; t_CKUINT m_num_dest; t_CKUINT m_max_src; t_CKTIME m_time; t_CKBOOL m_valid; t_CKBOOL m_use_next; SAMPLE m_sum; SAMPLE m_current; SAMPLE m_next; SAMPLE m_last; SAMPLE m_gain; SAMPLE m_pan; t_CKINT m_op; // the shred on which the ugen is created Chuck_VM_Shred * shred; // owner Chuck_UGen * owner; }; #endif chuck-1.2.0.8.dfsg/src/chuck_utils.cpp0000644000175000017500000000413110600421721016145 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_utils.cpp // desc: common utils // // author: Andrew Appel (appel@cs.princeton.edu) // modified: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2002 //----------------------------------------------------------------------------- #include #include #include #include "chuck_utils.h" #include "chuck_errmsg.h" void *checked_malloc( int len ) { if( !len ) return NULL; void *p = calloc( len, 1 ); if( !p ) { EM_error2( 0, "out of memory!\n" ); exit( 1 ); } return p; } c_str cc_str( char * s ) { c_str p = (c_str)checked_malloc( strlen(s)+1 ); strcpy( p, s ); return p; } U_boolList U_BoolList( t_CKBOOL head, U_boolList tail ) { U_boolList list = (U_boolList)checked_malloc( sizeof(*list) ); list->head = head; list->tail = tail; return list; } chuck-1.2.0.8.dfsg/src/chuck_utils.h0000644000175000017500000000363010600421721015615 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_utils.h // desc: common utils // // author: Andrew Appel (appel@cs.princeton.edu // modified: Ge Wang (gewang.cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_UTILS_H__ #define __CHUCK_UTILS_H__ #include "chuck_def.h" #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif typedef struct U_boolList_ * U_boolList; struct U_boolList_ { t_CKBOOL head; U_boolList tail; }; void * checked_malloc( int size ); c_str cc_str( char * ); U_boolList U_BoolList( t_CKBOOL head, U_boolList tail ); #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/chuck_vm.cpp0000644000175000017500000014433010600421721015435 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_vm.cpp // desc: ... // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #include "chuck_vm.h" #include "chuck_instr.h" #include "chuck_bbq.h" #include "chuck_errmsg.h" #include "chuck_dl.h" #include "chuck_type.h" #include "chuck_globals.h" #include "ugen_xxx.h" using namespace std; #if defined(__PLATFORM_WIN32__) #include #else #include #include #endif //----------------------------------------------------------------------------- // name: struct Chuck_VM_Frame // desc: func frame //----------------------------------------------------------------------------- struct Chuck_VM_Frame { public: t_CKUINT size; public: Chuck_VM_Frame() { size = 0; } ~Chuck_VM_Frame() { } }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Func // desc: vm function //----------------------------------------------------------------------------- struct Chuck_VM_Func { public: Chuck_VM_Code * code; Chuck_VM_Frame * frame; t_CKUINT index; public: Chuck_VM_Func() { code = NULL; frame = NULL; index = 0; } ~Chuck_VM_Func() { } }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_FTable // desc: function table //----------------------------------------------------------------------------- struct Chuck_VM_FTable { public: Chuck_VM_FTable(); ~Chuck_VM_FTable(); public: Chuck_VM_Func * get_func( t_CKUINT index ); t_CKUINT append( Chuck_VM_Func * f ); t_CKBOOL remove( t_CKUINT index ); public: vector func_table; }; //----------------------------------------------------------------------------- // name: Chuck_VM() // desc: ... //----------------------------------------------------------------------------- Chuck_VM::Chuck_VM() { m_shreds = NULL; m_num_shreds = 0; m_shreduler = NULL; m_msg_buffer = NULL; m_reply_buffer = NULL; m_event_buffer = NULL; m_shred_id = 0; m_halt = TRUE; m_audio = FALSE; m_block = TRUE; m_running = FALSE; m_audio_started = FALSE; m_dac = NULL; m_adc = NULL; m_bunghole = NULL; m_num_dac_channels = 0; m_num_adc_channels = 0; m_init = FALSE; } //----------------------------------------------------------------------------- // name: ~Chuck_VM() // desc: ... //----------------------------------------------------------------------------- Chuck_VM::~Chuck_VM() { if( m_init ) shutdown(); } // dac tick //UGEN_TICK __dac_tick( Chuck_Object * SELF, SAMPLE in, SAMPLE * out ) //{ *out = in; return TRUE; } //UGEN_TICK __bunghole_tick( Chuck_Object * SELF, SAMPLE in, SAMPLE * out ) //{ *out = 0.0f; return TRUE; } // static #ifdef __MACOSX_CORE__ t_CKINT Chuck_VM::our_priority = 85; #else t_CKINT Chuck_VM::our_priority = 0x7fffffff; #endif #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) //----------------------------------------------------------------------------- // name: set_priority() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::set_priority( t_CKINT priority, Chuck_VM * vm ) { struct sched_param param; pthread_t tid = pthread_self(); int policy; // log EM_log( CK_LOG_INFO, "setting thread priority to: %ld...", priority ); // get for thread if( pthread_getschedparam( tid, &policy, ¶m) ) { if( vm ) vm->m_last_error = "could not get current scheduling parameters"; return FALSE; } // priority param.sched_priority = priority; // policy policy = SCHED_RR; // set for thread if( pthread_setschedparam( tid, policy, ¶m ) ) { if( vm ) vm->m_last_error = "could not set new scheduling parameters"; return FALSE; } return TRUE; } #else //----------------------------------------------------------------------------- // name: set_priority() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::set_priority( t_CKINT priority, Chuck_VM * vm ) { // if priority is 0 then done if( !priority ) return TRUE; // set the priority class of the process // if( !SetPriorityClass( GetCurrentProcess(), HIGH_PRIORITY_CLASS ) ) // return FALSE; // log EM_log( CK_LOG_INFO, "setting thread priority to: %ld...", priority ); // set the priority the thread // if( !SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL ) ) if( !SetThreadPriority( GetCurrentThread(), priority ) ) { if( vm ) vm->m_last_error = "could not set new scheduling parameters"; return FALSE; } return TRUE; } #endif //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::initialize( t_CKBOOL enable_audio, t_CKBOOL halt, t_CKUINT srate, t_CKUINT buffer_size, t_CKUINT num_buffers, t_CKUINT dac, t_CKUINT adc, t_CKUINT dac_chan, t_CKUINT adc_chan, t_CKBOOL block ) { if( m_init ) { m_last_error = "VM already initialized!"; return FALSE; } // boost thread priority // if( priority != 0x7fffffff && !set_priority( priority, this ) ) // return FALSE; // log EM_log( CK_LOG_SYSTEM, "initializing virtual machine..." ); EM_pushlog(); // push stack EM_log( CK_LOG_SYSTEM, "behavior: %s", halt ? "HALT" : "LOOP" ); // allocate bbq m_bbq = new BBQ; m_halt = halt; m_audio = enable_audio; m_block = block; // log EM_log( CK_LOG_SYSTEM, "allocating shreduler..." ); // allocate shreduler m_shreduler = new Chuck_VM_Shreduler; m_shreduler->bbq = m_bbq; m_shreduler->rt_audio = enable_audio; // log EM_log( CK_LOG_SYSTEM, "allocating messaging buffers..." ); // allocate msg buffer m_msg_buffer = new CBufferSimple; m_msg_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_msg_buffer->join(); // this should return 0 m_reply_buffer = new CBufferSimple; m_reply_buffer->initialize( 1024, sizeof(Chuck_Msg *) ); //m_reply_buffer->join(); // this should return 0 too m_event_buffer = new CBufferSimple; m_event_buffer->initialize( 1024, sizeof(Chuck_Event *) ); //m_event_buffer->join(); // this should also return 0 // log EM_log( CK_LOG_SYSTEM, "real-time audio: %s", enable_audio ? "YES" : "NO" ); EM_log( CK_LOG_SYSTEM, "mode: %s", block ? "BLOCKING" : "CALLBACK" ); EM_log( CK_LOG_SYSTEM, "sample rate: %ld", srate ); EM_log( CK_LOG_SYSTEM, "buffer size: %ld", buffer_size ); if( enable_audio ) { EM_log( CK_LOG_SYSTEM, "num buffers: %ld", num_buffers ); EM_log( CK_LOG_SYSTEM, "devices adc: %ld dac: %d (default 0)", adc, dac ); } EM_log( CK_LOG_SYSTEM, "channels in: %ld out: %ld", adc_chan, dac_chan ); m_num_adc_channels = adc_chan; m_num_dac_channels = dac_chan; // at least set the sample rate and buffer size m_bbq->set_srate( srate ); m_bbq->set_bufsize( buffer_size ); m_bbq->set_numbufs( num_buffers ); m_bbq->set_inouts( adc, dac ); m_bbq->set_chans( adc_chan, dac_chan ); // pop log EM_poplog(); return m_init = TRUE; } //----------------------------------------------------------------------------- // name: initialize_synthesis() // desc: requires type system //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::initialize_synthesis( ) { if( !m_init ) { m_last_error = "VM initialize_synthesis() called on raw VM"; return FALSE; } if( !g_t_dac || !g_t_adc ) { m_last_error = "VM initialize_synthesis() called before type system initialized"; return FALSE; } if( m_dac != NULL ) { m_last_error = "VM synthesis already initialized"; return FALSE; } // log EM_log( CK_LOG_SYSTEM, "initializing synthesis engine..." ); // push indent EM_pushlog(); // log EM_log( CK_LOG_SEVERE, "initializing 'dac'..." ); // allocate dac and adc g_t_dac->ugen_info->num_outs = g_t_dac->ugen_info->num_ins = m_num_dac_channels; m_dac = (Chuck_UGen *)instantiate_and_initialize_object( g_t_dac, NULL ); stereo_ctor( m_dac, NULL, NULL ); // TODO: is the NULL shred a problem? multi_ctor( m_dac, NULL, NULL ); // TODO: remove and let type system do this m_dac->add_ref(); // lock it m_dac->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'adc'..." ); g_t_dac->ugen_info->num_ins = g_t_adc->ugen_info->num_outs = m_num_adc_channels; m_adc = (Chuck_UGen *)instantiate_and_initialize_object( g_t_adc, NULL ); stereo_ctor( m_adc, NULL, NULL ); multi_ctor( m_adc, NULL, NULL ); // TODO: remove and let type system do this m_adc->add_ref(); // lock it m_adc->lock(); // log EM_log( CK_LOG_SEVERE, "initializing 'blackhole'..." ); m_bunghole = new Chuck_UGen; m_bunghole->add_ref(); m_bunghole->lock(); initialize_object( m_bunghole, &t_ugen ); m_bunghole->tick = NULL; m_shreduler->m_dac = m_dac; m_shreduler->m_adc = m_adc; m_shreduler->m_bunghole = m_bunghole; m_shreduler->m_num_dac_channels = m_num_dac_channels; m_shreduler->m_num_adc_channels = m_num_adc_channels; // log EM_log( CK_LOG_SYSTEM, "initializing '%s' audio...", m_audio ? "real-time" : "fake-time" ); // init bbq if( !m_bbq->initialize( m_num_dac_channels, m_num_adc_channels, Digitalio::m_sampling_rate, 16, Digitalio::m_buffer_size, Digitalio::m_num_buffers, Digitalio::m_dac_n, Digitalio::m_adc_n, m_block, this, m_audio ) ) { m_last_error = "cannot initialize audio device (try using --silent/-s)"; // pop indent EM_poplog(); return FALSE; } // pop indent EM_poplog(); return TRUE; } //----------------------------------------------------------------------------- // name: compensate_bbq() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM::compensate_bbq() { // set shreduler - the audio was initialized elsewhere m_shreduler->bbq = m_bbq; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::shutdown() { // make sure we are in the initialized state if( !m_init ) return FALSE; // log EM_log( CK_LOG_SYSTEM, "shutting down virtual machine..." ); // push indent EM_pushlog(); // stop if( m_running ) { this->stop(); usleep( 50000 ); } // shutdown audio if( m_audio ) { // log EM_log( CK_LOG_SYSTEM, "shutting down real-time audio..." ); m_bbq->digi_out()->cleanup(); m_bbq->digi_in()->cleanup(); m_bbq->shutdown(); SAFE_DELETE( m_bbq ); m_audio = FALSE; } // log EM_log( CK_LOG_SYSTEM, "freeing shreduler..." ); // free the shreduler SAFE_DELETE( m_shreduler ); // log EM_log( CK_LOG_SEVERE, "clearing shreds..." ); // terminate shreds Chuck_VM_Shred * curr = m_shreds, * prev = NULL; while( curr ) { prev = curr; curr = curr->next; // delete prev; } m_shreds = NULL; m_num_shreds = 0; m_init = FALSE; // pop indent EM_poplog(); return TRUE; } //----------------------------------------------------------------------------- // name: start_audio() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::start_audio( ) { // audio if( !m_audio_started && m_audio ) { EM_log( CK_LOG_SEVERE, "starting real-time audio..." ); m_bbq->digi_out()->start(); m_bbq->digi_in()->start(); } // set the flag to true to avoid entering this function m_audio_started = TRUE; return TRUE; } //----------------------------------------------------------------------------- // name: run() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::run( ) { // check if init if( m_dac == NULL ) { m_last_error = "VM and/or synthesis not initialized..."; return FALSE; } // check if already running if( m_running ) { m_last_error = "virtual machine already running..."; return FALSE; } m_running = TRUE; // log EM_log( CK_LOG_SYSTEM, "running virtual machine..." ); // push indent EM_pushlog(); // audio //if( m_audio ) //{ // log EM_log( CK_LOG_SEVERE, "initializing audio buffers..." ); if( !m_bbq->digi_out()->initialize( ) ) { m_last_error = "cannot open audio output (option: use --silent/-s)"; return FALSE; } m_bbq->digi_in()->initialize( ); //} // log EM_log( CK_LOG_SEVERE, "virtual machine running..." ); // pop indent EM_poplog(); // run if( m_block ) this->run( -1 ); else { // compute shreds before first sample if( !compute() ) { // done m_running = FALSE; // log EM_log( CK_LOG_SYSTEM, "virtual machine stopped..." ); } else { // start audio if( !m_audio_started ) start_audio(); // wait while( m_running ) { usleep( 50000 ); } } } return TRUE; } /*should we comment out what we just did? i can't think of why it might be affecting this part of the vm you never know true*/ //----------------------------------------------------------------------------- // name: compute() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::compute() { Chuck_VM_Shred * shred = NULL; Chuck_Msg * msg = NULL; Chuck_Event * event = NULL; t_CKBOOL iterate = TRUE; // iteration until no more shreds/events/messages while( iterate ) { // get the shreds queued for 'now' while(( shred = m_shreduler->get() )) { // set the current time of the shred shred->now = shred->wake_time; // track shred activation CK_TRACK( Chuck_Stats::instance()->activate_shred( shred ) ); // run the shred if( !shred->run( this ) ) { // track shred deactivation CK_TRACK( Chuck_Stats::instance()->deactivate_shred( shred ) ); this->free( shred, TRUE ); shred = NULL; if( !m_num_shreds && m_halt ) return FALSE; } // track shred deactivation CK_TRACK( if( shred ) Chuck_Stats::instance()->deactivate_shred( shred ) ); } // set to false for now iterate = FALSE; // broadcast queued events while( m_event_buffer->get( &event, 1 ) ) { event->broadcast(); iterate = TRUE; } // process messages while( m_msg_buffer->get( &msg, 1 ) ) { process_msg( msg ); iterate = TRUE; } } return TRUE; } //----------------------------------------------------------------------------- // name: run() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::run( t_CKINT num_samps ) { // loop it while( num_samps ) { // compute shreds if( !compute() ) goto vm_stop; // start audio if( !m_audio_started ) start_audio(); // advance the shreduler m_shreduler->advance(); // count if( num_samps > 0 ) num_samps--; } return FALSE; // vm stop here vm_stop: m_running = FALSE; // log EM_log( CK_LOG_SYSTEM, "virtual machine stopped..." ); return TRUE; } //----------------------------------------------------------------------------- // name: pause() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::pause( ) { m_running = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: stop() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::stop( ) { // log EM_log( CK_LOG_SEVERE, "requesting STOP virtual machine..." ); m_running = FALSE; Digitalio::m_end = TRUE; return TRUE; } //----------------------------------------------------------------------------- // name: gc // desc: ... //----------------------------------------------------------------------------- void Chuck_VM::gc( t_CKUINT amount ) { } //----------------------------------------------------------------------------- // name: gc // desc: ... //----------------------------------------------------------------------------- void Chuck_VM::gc( ) { } //----------------------------------------------------------------------------- // name: queue_msg() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::queue_msg( Chuck_Msg * msg, int count ) { assert( count == 1 ); m_msg_buffer->put( &msg, count ); return TRUE; } //----------------------------------------------------------------------------- // name: queue_event() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::queue_event( Chuck_Event * event, int count ) { assert( count == 1 ); m_event_buffer->put( &event, count ); return TRUE; } //----------------------------------------------------------------------------- // name: get_reply() // desc: ... //----------------------------------------------------------------------------- Chuck_Msg * Chuck_VM::get_reply( ) { Chuck_Msg * msg = NULL; m_reply_buffer->get( &msg, 1 ); return msg; } //----------------------------------------------------------------------------- // name: process_msg() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_VM::process_msg( Chuck_Msg * msg ) { t_CKUINT retval = 0xfffffff0; if( msg->type == MSG_REPLACE ) { Chuck_VM_Shred * out = m_shreduler->lookup( msg->param ); if( !out ) { EM_error3( "[chuck](VM): error replacing shred: no shred with id %i...", msg->param ); retval = 0; goto done; } Chuck_VM_Shred * shred = msg->shred; if( !shred ) { shred = new Chuck_VM_Shred; shred->initialize( msg->code ); shred->name = msg->code->name; shred->base_ref = shred->mem; shred->add_ref(); } // set the current time shred->start = m_shreduler->now_system; // set the id shred->xid = msg->param; // set the now shred->now = shred->wake_time = m_shreduler->now_system; // set the vm shred->vm_ref = this; // set args if( msg->args ) shred->args = *(msg->args); // add it to the parent if( shred->parent ) shred->parent->children[shred->xid] = shred; // replace if( m_shreduler->remove( out ) && m_shreduler->shredule( shred ) ) { EM_error3( "[chuck](VM): replacing shred %i (%s) with %i (%s)...", out->xid, mini(out->name.c_str()), shred->xid, mini(shred->name.c_str()) ); this->free( out, TRUE, FALSE ); retval = shred->xid; // tracking new shred CK_TRACK( Chuck_Stats::instance()->add_shred( shred ) ); goto done; } else { EM_error3( "[chuck](VM): shreduler ERROR replacing shred %i...", out->xid ); shred->release(); retval = 0; goto done; } } else if( msg->type == MSG_REMOVE ) { if( msg->param == 0xffffffff ) { if( !this->m_num_shreds) { EM_error3( "[chuck](VM): no shreds to remove..." ); retval = 0; goto done; } t_CKINT xid = m_shred_id; Chuck_VM_Shred * shred = NULL; while( xid >= 0 && m_shreduler->remove( shred = m_shreduler->lookup( xid ) ) == 0 ) xid--; if( xid >= 0 ) { EM_error3( "[chuck](VM): removing recent shred: %i (%s)...", xid, mini(shred->name.c_str()) ); this->free( shred, TRUE ); retval = xid; } else { EM_error3( "[chuck](VM): no shreds removed..." ); retval = 0; goto done; } } else { Chuck_VM_Shred * shred = m_shreduler->lookup( msg->param ); if( !shred ) { EM_error3( "[chuck](VM): cannot remove: no shred with id %i...", msg->param ); retval = 0; goto done; } if( !m_shreduler->remove( shred ) ) // was lookup { EM_error3( "[chuck](VM): shreduler: cannot remove shred %i...", msg->param ); retval = 0; goto done; } EM_error3( "[chuck](VM): removing shred: %i (%s)...", msg->param, mini(shred->name.c_str()) ); this->free( shred, TRUE ); retval = msg->param; } } else if( msg->type == MSG_REMOVEALL ) { t_CKUINT xid = m_shred_id; EM_error3( "[chuck](VM): removing all (%i) shreds...", m_num_shreds ); Chuck_VM_Shred * shred = NULL; while( m_num_shreds && xid > 0 ) { if( m_shreduler->remove( shred = m_shreduler->lookup( xid ) ) ) this->free( shred, TRUE ); xid--; } m_shred_id = 0; m_num_shreds = 0; } else if( msg->type == MSG_ADD ) { t_CKUINT xid = 0; Chuck_VM_Shred * shred = NULL; if( msg->shred ) shred = this->spork( msg->shred ); else shred = this->spork( msg->code, NULL ); xid = shred->xid; if( msg->args ) shred->args = *(msg->args); const char * s = ( msg->shred ? msg->shred->name.c_str() : msg->code->name.c_str() ); EM_error3( "[chuck](VM): sporking incoming shred: %i (%s)...", xid, mini(s) ); retval = xid; goto done; } else if( msg->type == MSG_KILL ) { EM_error3( "[chuck](VM): KILL received...." ); // close file handles and clean up all_detach(); // TODO: free more memory? // log EM_log( CK_LOG_INFO, "(VM): exiting..." ); // come again exit( 1 ); } else if( msg->type == MSG_STATUS ) { m_shreduler->status(); } else if( msg->type == MSG_TIME ) { float srate = (float)Digitalio::sampling_rate(); fprintf( stderr, "[chuck](VM): the values of now:\n" ); fprintf( stderr, " now = %.6f (samp)\n", m_shreduler->now_system ); fprintf( stderr, " = %.6f (second)\n", m_shreduler->now_system / srate ); fprintf( stderr, " = %.6f (minute)\n", m_shreduler->now_system / srate / 60.0f ); fprintf( stderr, " = %.6f (hour)\n", m_shreduler->now_system / srate / 60.0f / 60.0f ); fprintf( stderr, " = %.6f (day)\n", m_shreduler->now_system / srate / 60.0f / 60.0f / 24.0f ); fprintf( stderr, " = %.6f (week)\n", m_shreduler->now_system / srate / 60.0f / 60.0f / 24.0f / 7.0f ); } else if( msg->type == MSG_RESET_ID ) { t_CKUINT n = m_shreduler->highest(); m_shred_id = n; fprintf( stderr, "[chuck](VM): reseting shred id to %d...\n", m_shred_id + 1 ); } done: if( msg->reply ) { msg->replyA = retval; m_reply_buffer->put( &msg, 1 ); } else SAFE_DELETE(msg); return retval; } //----------------------------------------------------------------------------- // name: next_id() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_VM::next_id( ) { return ++m_shred_id; } //----------------------------------------------------------------------------- // name: shreduler() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shreduler * Chuck_VM::shreduler( ) const { return m_shreduler; } //----------------------------------------------------------------------------- // name: bbq() // desc: ... //----------------------------------------------------------------------------- BBQ * Chuck_VM::bbq( ) const { return m_bbq; } //----------------------------------------------------------------------------- // name: srate() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_VM::srate() const { return (t_CKUINT)Digitalio::sampling_rate(); } //----------------------------------------------------------------------------- // name: fork() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred * Chuck_VM::fork( Chuck_VM_Code * code ) { return NULL; } //----------------------------------------------------------------------------- // name: spork() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred * Chuck_VM::spork( Chuck_VM_Code * code, Chuck_VM_Shred * parent ) { // allocate a new shred Chuck_VM_Shred * shred = new Chuck_VM_Shred; // initialize the shred (default stack size) shred->initialize( code ); // set the name shred->name = code->name; // set the parent shred->parent = parent; // add ref shred->add_ref(); // set the base ref for global if( parent ) shred->base_ref = shred->parent->base_ref; else shred->base_ref = shred->mem; // spork it this->spork( shred ); // track new shred CK_TRACK( Chuck_Stats::instance()->add_shred( shred ) ); return shred; } //----------------------------------------------------------------------------- // name: spork() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred * Chuck_VM::spork( Chuck_VM_Shred * shred ) { // set the current time shred->start = m_shreduler->now_system; // set the now shred->now = shred->wake_time = m_shreduler->now_system; // set the id shred->xid = next_id(); // set the vm shred->vm_ref = this; // add it to the parent if( shred->parent ) shred->parent->children[shred->xid] = shred; // shredule it m_shreduler->shredule( shred ); // count m_num_shreds++; return shred; } //----------------------------------------------------------------------------- // name: free() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM::free( Chuck_VM_Shred * shred, t_CKBOOL cascade, t_CKBOOL dec ) { assert( cascade ); // mark this done shred->is_done = TRUE; // free the children t_CKINT size = shred->children.size(); if( size ) { vector list; list.resize( size ); map::iterator iter; t_CKINT i = 0; for( iter = shred->children.begin(); iter != shred->children.end(); iter++ ) list[i++] = (*iter).second; for( i = 0; i < size; i++ ) this->free( list[i], cascade ); } // make sure it's done assert( shred->children.size() == 0 ); // tell parent if( shred->parent ) shred->parent->children.erase( shred->xid ); // track remove shred CK_TRACK( Chuck_Stats::instance()->remove_shred( shred ) ); // free! m_shreduler->remove( shred ); // TODO: remove shred from event, with synchronization // if( shred->event ) shred->event->remove( shred ); shred->release(); shred = NULL; if( dec ) m_num_shreds--; if( !m_num_shreds ) m_shred_id = 0; return TRUE; } //----------------------------------------------------------------------------- // name: Chuck_VM_Stack() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Stack::Chuck_VM_Stack() { stack = sp = sp_max = NULL; prev = next = NULL; m_is_init = FALSE; } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Stack() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Stack::~Chuck_VM_Stack() { this->shutdown(); } //----------------------------------------------------------------------------- // name: Chuck_VM_Code() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code::Chuck_VM_Code() { instr = NULL; num_instr = 0; stack_depth = 0; need_this = FALSE; native_func = 0; native_func_type = NATIVE_UNKNOWN; } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Code() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Code::~Chuck_VM_Code() { // free instructions if( instr ) { // loop over array for( t_CKUINT i = 0; i < num_instr; i++ ) delete instr[i]; // free the array SAFE_DELETE_ARRAY( instr ); } num_instr = 0; } // offset in bytes at the beginning of a stack for initializing data #define VM_STACK_OFFSET 16 // 1/factor of stack is left blank, to give room to detect overflow #define VM_STACK_PADDING_FACTOR 16 //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Stack::initialize( t_CKUINT size ) { if( m_is_init ) return FALSE; // make room for header size += VM_STACK_OFFSET; // allocate stack stack = new t_CKBYTE[size]; if( !stack ) goto out_of_memory; // zero memset( stack, 0, size ); // advance stack after the header stack += VM_STACK_OFFSET; // set the sp sp = stack; // upper limit (padding factor) sp_max = sp + size - (size / VM_STACK_PADDING_FACTOR); // set flag and return return m_is_init = TRUE; out_of_memory: // we have a problem fprintf( stderr, "[chuck](VM): OutOfMemory: while allocating stack '%s'\n" ); // return FALSE return FALSE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Stack::shutdown() { if( !m_is_init ) return FALSE; // free the stack stack -= VM_STACK_OFFSET; SAFE_DELETE_ARRAY( stack ); sp = sp_max = NULL; // set the flag to false m_is_init = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: Chuck_VM_Shred() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred::Chuck_VM_Shred() { mem = new Chuck_VM_Stack; reg = new Chuck_VM_Stack; code = NULL; next = prev = NULL; instr = NULL; parent = NULL; obj_array = NULL; obj_array_size = 0; base_ref = NULL; vm_ref = NULL; event = NULL; // set CK_TRACK( stat = NULL ); } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Shred() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred::~Chuck_VM_Shred() { this->shutdown(); } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shred::initialize( Chuck_VM_Code * c, t_CKUINT mem_stack_size, t_CKUINT reg_stack_size ) { // allocate mem and reg if( !mem->initialize( mem_stack_size ) ) return FALSE; if( !reg->initialize( reg_stack_size ) ) return FALSE; // program counter pc = 0; next_pc = 1; // code pointer code_orig = code = c; // add reference code_orig->add_ref(); // shred done is_done = FALSE; // shred running is_running = FALSE; // set the instr instr = c->instr; // zero out the id xid = 0; // initialize initialize_object( this, &t_shred ); return TRUE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shred::shutdown() { // get iterator to our map map::iterator iter = m_ugen_map.begin(); while( iter != m_ugen_map.end() ) { (*iter).first->disconnect( TRUE ); iter++; } m_ugen_map.clear(); SAFE_DELETE( mem ); SAFE_DELETE( reg ); base_ref = NULL; // delete temp pointer space SAFE_DELETE_ARRAY( obj_array ); obj_array_size = 0; // TODO: is this right? code_orig->release(); code_orig = code = NULL; // what to do with next and prev? return TRUE; } //----------------------------------------------------------------------------- // name: add() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shred::add( Chuck_UGen * ugen ) { if( m_ugen_map[ugen] ) return FALSE; m_ugen_map[ugen] = ugen; return TRUE; } //----------------------------------------------------------------------------- // name: remove() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shred::remove( Chuck_UGen * ugen ) { if( !m_ugen_map[ugen] ) return FALSE; // remove it m_ugen_map.erase( ugen ); return TRUE; } //----------------------------------------------------------------------------- // name: run() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shred::run( Chuck_VM * vm ) { // get the code instr = code->instr; is_running = TRUE; t_CKBOOL * vm_running = &vm->m_running; // go! while( is_running && *vm_running ) { // execute the instruction instr[pc]->execute( vm, this ); // set to next_pc; pc = next_pc; next_pc++; // track number of cycles CK_TRACK( this->stat->cycles++ ); } // is the shred finished return !is_done; } //----------------------------------------------------------------------------- // name: Chuck_VM_Shreduler() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shreduler::Chuck_VM_Shreduler() { now_system = 0; rt_audio = FALSE; bbq = NULL; shred_list = NULL; m_dac = NULL; m_adc = NULL; m_bunghole = NULL; m_num_dac_channels = 0; m_num_adc_channels = 0; } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Shreduler() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shreduler::~Chuck_VM_Shreduler() { this->shutdown(); } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::initialize() { return TRUE; } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::shutdown() { return TRUE; } //----------------------------------------------------------------------------- // name: add_blocked() // desc: add shred to the shreduler's blocked list //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::add_blocked( Chuck_VM_Shred * shred ) { // add shred to map, using pointer blocked[shred] = shred; return TRUE; } //----------------------------------------------------------------------------- // name: remove_blocked() // desc: remove shred from the shreduler's blocked list //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::remove_blocked( Chuck_VM_Shred * shred ) { // remove from hash std::map::iterator iter; iter = blocked.find( shred ); blocked.erase( iter ); // remove from event if( shred->event != NULL ) shred->event->remove( shred ); return TRUE; } //----------------------------------------------------------------------------- // name: shredule() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::shredule( Chuck_VM_Shred * shred ) { return this->shredule( shred, now_system ); } //----------------------------------------------------------------------------- // name: shredule() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::shredule( Chuck_VM_Shred * shred, t_CKTIME wake_time ) { // sanity check if( shred->prev || shred->next ) { // something is really wrong here - no shred can be // shreduled more than once EM_error3( "[chuck](VM): internal sanity check failed in shredule()" ); EM_error3( "[chuck](VM): (shred shreduled while shreduled)" ); return FALSE; } // sanity check if( wake_time < (this->now_system - .5) ) { // trying to enqueue on a time that is less than now EM_error3( "[chuck](VM): internal sanity check failed in shredule()" ); EM_error3( "[chuck](VM): (wake time is past) - %f : %f", wake_time, this->now_system ); return FALSE; } shred->wake_time = wake_time; // list empty if( !shred_list ) shred_list = shred; else { // pointers to the shred queue Chuck_VM_Shred * curr = shred_list; Chuck_VM_Shred * prev = NULL; while( curr ) { // found the place to insert if( curr->wake_time > wake_time ) break; prev = curr; curr = curr->next; } if( !prev ) { shred->next = shred_list; if( shred_list ) shred_list->prev = shred; shred_list = shred; } else { // insert the shred in sorted order shred->next = prev->next; shred->prev = prev; if( prev->next ) prev->next->prev = shred; prev->next = shred; } } return TRUE; } //----------------------------------------------------------------------------- // name: advance2() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM_Shreduler::advance2( ) { // advance system 'now' this->now_system += 1; // tick the dac SAMPLE l, r; BBQ * audio = this->bbq; // tick in if( rt_audio ) { audio->digi_in()->tick_in( &l, &r ); m_adc->m_multi_chan[0]->m_current = l * m_adc->m_multi_chan[0]->m_gain; m_adc->m_multi_chan[1]->m_current = r * m_adc->m_multi_chan[1]->m_gain; m_adc->m_current = .5f * ( l + r ); // time it m_adc->m_multi_chan[0]->m_time = this->now_system; m_adc->m_multi_chan[1]->m_time = this->now_system; m_adc->m_time = this->now_system; } // dac m_dac->system_tick( this->now_system ); l = m_dac->m_multi_chan[0]->m_current; r = m_dac->m_multi_chan[1]->m_current; l *= .5f; r *= .5f; // suck samples m_bunghole->system_tick( this->now_system ); // tick audio->digi_out()->tick_out( l, r ); } //----------------------------------------------------------------------------- // name: advance() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM_Shreduler::advance( ) { // advance system 'now' this->now_system += 1; // tick the dac SAMPLE frame[128]; SAMPLE sum = 0.0f; BBQ * audio = this->bbq; t_CKUINT i; // tick in if( rt_audio ) { audio->digi_in()->tick_in( frame, m_num_adc_channels ); // loop over channels for( i = 0; i < m_num_adc_channels; i++ ) { m_adc->m_multi_chan[i]->m_current = frame[i] * m_adc->m_multi_chan[i]->m_gain * m_adc->m_gain; m_adc->m_multi_chan[i]->m_time = this->now_system; sum += m_adc->m_multi_chan[i]->m_current; } m_adc->m_last = m_adc->m_current = sum / m_num_adc_channels; m_adc->m_time = this->now_system; } // dac m_dac->system_tick( this->now_system ); for( i = 0; i < m_num_dac_channels; i++ ) frame[i] = m_dac->m_multi_chan[i]->m_current * .5f; // suck samples m_bunghole->system_tick( this->now_system ); // tick audio->digi_out()->tick_out( frame, m_num_dac_channels ); } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred * Chuck_VM_Shreduler::get( ) { Chuck_VM_Shred * shred = shred_list; // list empty if( !shred ) return NULL; // TODO: should this be <=? if( shred->wake_time <= ( this->now_system + .5 ) ) { // if( shred->wake_time < this->now_system ) // assert( false ); shred_list = shred->next; shred->next = NULL; shred->prev = NULL; if( shred_list ) shred_list->prev = NULL; return shred; } return NULL; } //----------------------------------------------------------------------------- // name: highest() // desc: ... //----------------------------------------------------------------------------- t_CKUINT Chuck_VM_Shreduler::highest( ) { Chuck_VM_Shred * shred = shred_list; t_CKUINT n = 0; while( shred ) { if( shred->xid > n ) n = shred->xid; shred = shred->next; } std::map::iterator iter; for( iter = blocked.begin(); iter != blocked.end(); iter++ ) { shred = (*iter).second; if( shred->xid > n ) n = shred->xid; } return n; } //----------------------------------------------------------------------------- // name: replace() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::replace( Chuck_VM_Shred * out, Chuck_VM_Shred * in ) { assert( FALSE ); // sanity check if( !out || !in ) return FALSE; if( !out->prev ) shred_list = in; else out->prev->next = in; if( out->next ) out->next->prev = in; in->next = out->next; in->prev = out->prev; out->next = out->prev = NULL; in->wake_time = out->wake_time; in->start = in->wake_time; return TRUE; } //----------------------------------------------------------------------------- // name: remove() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL Chuck_VM_Shreduler::remove( Chuck_VM_Shred * out ) { if( !out ) return FALSE; // if blocked if( out->event != NULL ) { return remove_blocked( out ); } // sanity check if( !out->prev && !out->next && out != shred_list ) return FALSE; if( !out->prev ) shred_list = out->next; else out->prev->next = out->next; if( out->next ) out->next->prev = out->prev; out->next = out->prev = NULL; return TRUE; } //----------------------------------------------------------------------------- // name: get() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Shred * Chuck_VM_Shreduler::lookup( t_CKUINT xid ) { Chuck_VM_Shred * shred = shred_list; while( shred ) { if( shred->xid == xid ) return shred; shred = shred->next; } // blocked std::map::iterator iter; for( iter = blocked.begin(); iter != blocked.end(); iter++ ) { shred = (*iter).second; if( shred->xid == xid ) return shred; } return NULL; } //----------------------------------------------------------------------------- // name: SortByID() // desc: ... //----------------------------------------------------------------------------- struct SortByID { bool operator() ( const Chuck_VM_Shred * lhs, const Chuck_VM_Shred * rhs ) { return lhs->xid < rhs->xid; } }; //----------------------------------------------------------------------------- // name: status() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM_Shreduler::status( Chuck_VM_Status * status ) { Chuck_VM_Shred * shred = shred_list; t_CKUINT srate = Digitalio::sampling_rate(); t_CKUINT s = (t_CKUINT)now_system; t_CKUINT h = s/(srate*3600); s = s - (h*(srate*3600)); t_CKUINT m = s / (srate*60); s = s - (m*(srate*60)); t_CKUINT sec = s / srate; s = s - (sec*(srate)); // float millisecond = s / (float)(srate) * 1000.0f; status->srate = srate; status->now_system = now_system; status->t_second = sec; status->t_minute = m; status->t_hour = h; // get list of shreds vector list; while( shred ) { list.push_back( shred ); shred = shred->next; } // get blocked std::map::iterator iter; for( iter = blocked.begin(); iter != blocked.end(); iter++ ) { shred = (*iter).second; list.push_back( shred ); } // sort the list SortByID byid; std::sort( list.begin(), list.end(), byid ); // print status status->clear(); for( t_CKUINT i = 0; i < list.size(); i++ ) { shred = list[i]; status->list.push_back( new Chuck_VM_Shred_Status( shred->xid, shred->name, shred->start, shred->event != NULL ) ); } } //----------------------------------------------------------------------------- // name: status() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM_Shreduler::status( ) { Chuck_VM_Shred_Status * shred = NULL; this->status( &m_status ); t_CKUINT h = m_status.t_hour; t_CKUINT m = m_status.t_minute; t_CKUINT sec = m_status.t_second; fprintf( stdout, "[chuck](VM): status (now == %ldh%ldm%lds, %.1f samps) ...\n", h, m, sec, m_status.now_system ); // print status for( t_CKUINT i = 0; i < m_status.list.size(); i++ ) { shred = m_status.list[i]; fprintf( stdout, " [shred id]: %ld [source]: %s [spork time]: %.2fs ago%s\n", shred->xid, mini( shred->name.c_str() ), (m_status.now_system - shred->start) / m_status.srate, shred->has_event ? " (blocked)" : "" ); } } //----------------------------------------------------------------------------- // name: Chuck_VM_Status() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Status::Chuck_VM_Status() { srate = 0; now_system = 0; t_second = t_minute = t_hour = 0; } //----------------------------------------------------------------------------- // name: ~Chuck_VM_Status() // desc: ... //----------------------------------------------------------------------------- Chuck_VM_Status::~Chuck_VM_Status() { this->clear(); } //----------------------------------------------------------------------------- // name: clear() // desc: ... //----------------------------------------------------------------------------- void Chuck_VM_Status::clear() { for( t_CKUINT i = 0; i < list.size(); i++ ) { SAFE_DELETE( list[i] ); } list.clear(); } chuck-1.2.0.8.dfsg/src/chuck_vm.h0000644000175000017500000003210310600421721015074 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck_vm.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //----------------------------------------------------------------------------- #ifndef __CHUCK_VM_H__ #define __CHUCK_VM_H__ #include "chuck_oo.h" #include "chuck_ugen.h" // tracking #ifdef __CHUCK_STAT_TRACK__ #include "chuck_stats.h" #endif #include #include #include //----------------------------------------------------------------------------- // vm defines //----------------------------------------------------------------------------- #define CVM_MEM_STACK_SIZE (0x1 << 16) #define CVM_REG_STACK_SIZE (0x1 << 14) // forward references struct Chuck_Instr; struct Chuck_VM; struct Chuck_VM_Func; struct Chuck_VM_FTable; struct Chuck_Msg; class BBQ; class CBufferSimple; class Digitalio; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Stack // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Stack { //----------------------------------------------------------------------------- // functions //----------------------------------------------------------------------------- public: Chuck_VM_Stack(); ~Chuck_VM_Stack(); public: t_CKBOOL initialize( t_CKUINT size ); t_CKBOOL shutdown(); //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- public: // machine t_CKBYTE * stack; t_CKBYTE * sp; t_CKBYTE * sp_max; public: // linked list Chuck_VM_Stack * prev; Chuck_VM_Stack * next; public: // state t_CKBOOL m_is_init; }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Code // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Code : Chuck_Object { public: Chuck_VM_Code(); ~Chuck_VM_Code(); public: // array of Chuck_Instr *, should always end with Chuck_Instr_EOF Chuck_Instr ** instr; // size of the array t_CKUINT num_instr; // name of this code std::string name; // the depth of any function arguments t_CKUINT stack_depth; // whether the function needs 'this' pointer or not t_CKBOOL need_this; // native t_CKUINT native_func; // is ctor? t_CKUINT native_func_type; // native func types enum { NATIVE_UNKNOWN, NATIVE_CTOR, NATIVE_DTOR, NATIVE_MFUN, NATIVE_SFUN }; }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Shred // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Shred : Chuck_Object { //----------------------------------------------------------------------------- // functions //----------------------------------------------------------------------------- public: Chuck_VM_Shred( ); ~Chuck_VM_Shred( ); t_CKBOOL initialize( Chuck_VM_Code * c, t_CKUINT mem_st_size = CVM_MEM_STACK_SIZE, t_CKUINT reg_st_size = CVM_REG_STACK_SIZE ); t_CKBOOL shutdown(); t_CKBOOL run( Chuck_VM * vm ); t_CKBOOL add( Chuck_UGen * ugen ); t_CKBOOL remove( Chuck_UGen * ugen ); //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- public: // machine components // stacks Chuck_VM_Stack * mem; Chuck_VM_Stack * reg; // ref to base stack - if this is the root, then base is mem Chuck_VM_Stack * base_ref; // code Chuck_VM_Code * code; Chuck_VM_Code * code_orig; // the one to release Chuck_Instr ** instr; Chuck_VM_Shred * parent; std::map children; t_CKUINT pc; // vm Chuck_VM * vm_ref; // time t_CKTIME now; t_CKTIME start; // state t_CKUINT * obj_array; t_CKUINT obj_array_size; public: t_CKTIME wake_time; t_CKUINT next_pc; t_CKBOOL is_done; t_CKBOOL is_running; Chuck_Event * event; // event shred is waiting on std::map m_ugen_map; public: // id t_CKUINT xid; std::string name; std::vector args; public: Chuck_VM_Shred * prev; Chuck_VM_Shred * next; // tracking CK_TRACK( Shred_Stat * stat ); }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Shred_Status // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Shred_Status : Chuck_Object { public: t_CKUINT xid; std::string name; t_CKTIME start; t_CKBOOL has_event; public: Chuck_VM_Shred_Status( t_CKUINT _id, const std::string & n, t_CKTIME _start, t_CKBOOL e ) { xid = _id; name = n; start = _start; has_event = e; } }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Status // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Status : Chuck_Object { public: Chuck_VM_Status(); ~Chuck_VM_Status(); void clear(); public: // sample rate t_CKUINT srate; // now t_CKTIME now_system; // for display t_CKUINT t_second; t_CKUINT t_minute; t_CKUINT t_hour; // list of shred status std::vector list; }; //----------------------------------------------------------------------------- // name: struct Chuck_VM_Shreduler // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM_Shreduler : Chuck_Object { //----------------------------------------------------------------------------- // functions //----------------------------------------------------------------------------- public: Chuck_VM_Shreduler(); ~Chuck_VM_Shreduler(); public: t_CKBOOL initialize(); t_CKBOOL shutdown(); public: // shreduling t_CKBOOL shredule( Chuck_VM_Shred * shred ); t_CKBOOL shredule( Chuck_VM_Shred * shred, t_CKTIME wake_time ); Chuck_VM_Shred * get( ); void advance( ); void advance2( ); public: // high-level shred interface t_CKBOOL remove( Chuck_VM_Shred * shred ); t_CKBOOL replace( Chuck_VM_Shred * out, Chuck_VM_Shred * in ); Chuck_VM_Shred * lookup( t_CKUINT xid ); void status( ); void status( Chuck_VM_Status * status ); t_CKUINT highest(); public: // for event related shred queue t_CKBOOL add_blocked( Chuck_VM_Shred * shred ); t_CKBOOL remove_blocked( Chuck_VM_Shred * shred ); //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- public: // time and audio t_CKTIME now_system; t_CKBOOL rt_audio; BBQ * bbq; // shreds to be shreduled Chuck_VM_Shred * shred_list; // shreds waiting on events std::map blocked; // ugen Chuck_UGen * m_dac; Chuck_UGen * m_adc; Chuck_UGen * m_bunghole; t_CKUINT m_num_dac_channels; t_CKUINT m_num_adc_channels; // status cache Chuck_VM_Status m_status; }; //----------------------------------------------------------------------------- // name: struct Chuck_VM // desc: ... //----------------------------------------------------------------------------- struct Chuck_VM : Chuck_Object { //----------------------------------------------------------------------------- // functions //----------------------------------------------------------------------------- public: Chuck_VM(); ~Chuck_VM(); public: // init t_CKBOOL initialize( t_CKBOOL enable_audio = TRUE, t_CKBOOL halt = TRUE, t_CKUINT srate = 44100, t_CKUINT buffer_size = 512, t_CKUINT num_buffers = 4, t_CKUINT dac = 0, t_CKUINT adc = 0, t_CKUINT dac_chan = 2, t_CKUINT adc_chan = 2, t_CKBOOL block = TRUE ); t_CKBOOL initialize_synthesis( ); t_CKBOOL shutdown(); public: // shreds Chuck_VM_Shred * spork( Chuck_VM_Code * code, Chuck_VM_Shred * parent ); Chuck_VM_Shred * fork( Chuck_VM_Code * code ); Chuck_VM_Shreduler * shreduler() const; t_CKUINT next_id( ); public: // audio BBQ * bbq() const; t_CKUINT srate() const; void compensate_bbq(); public: // running the machine t_CKBOOL run( ); t_CKBOOL run( t_CKINT num_samps ); t_CKBOOL compute( ); t_CKBOOL pause( ); t_CKBOOL stop( ); t_CKBOOL start_audio( ); public: // invoke functions t_CKBOOL invoke_static( Chuck_VM_Shred * shred ); public: // garbage collection void gc(); void gc( t_CKUINT amount ); public: // msg t_CKBOOL queue_msg( Chuck_Msg * msg, int num_msg ); t_CKBOOL queue_event( Chuck_Event * event, int num_msg ); t_CKUINT process_msg( Chuck_Msg * msg ); Chuck_Msg * get_reply( ); public: // static/dynamic function table //void set_env( void * env ) { m_env = env; } //void * get_env( ) { return m_env; } t_CKBOOL has_init() { return m_init; } t_CKBOOL is_running() { return m_running; } public: // get error const char * last_error() const { return m_last_error.c_str(); } //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- public: // ugen Chuck_UGen * m_adc; Chuck_UGen * m_dac; Chuck_UGen * m_bunghole; t_CKUINT m_num_adc_channels; t_CKUINT m_num_dac_channels; t_CKBOOL m_halt; t_CKBOOL m_audio; t_CKBOOL m_block; protected: Chuck_VM_Shred * spork( Chuck_VM_Shred * shred ); t_CKBOOL free( Chuck_VM_Shred * shred, t_CKBOOL cascade, t_CKBOOL dec = TRUE ); protected: t_CKBOOL m_init; // t_CKBOOL m_running; -> moved to public t_CKBOOL m_audio_started; std::string m_last_error; // shred Chuck_VM_Shred * m_shreds; t_CKUINT m_num_shreds; t_CKUINT m_shred_id; Chuck_VM_Shreduler * m_shreduler; // audio BBQ * m_bbq; // function table // Chuck_VM_FTable * m_func_table; // t_CKUINT m_num_func; // message queue CBufferSimple * m_msg_buffer; CBufferSimple * m_reply_buffer; CBufferSimple * m_event_buffer; public: // running t_CKBOOL m_running; // priority static t_CKBOOL set_priority( t_CKINT priority, Chuck_VM * vm ); static t_CKINT our_priority; }; //----------------------------------------------------------------------------- // name: enum Chuck_Msg_Type // desc: ... //----------------------------------------------------------------------------- enum Chuck_Msg_Type { MSG_ADD = 1, MSG_REMOVE, MSG_REMOVEALL, MSG_REPLACE, MSG_STATUS, MSG_PAUSE, MSG_KILL, MSG_TIME, MSG_RESET_ID, MSG_DONE }; // callback function prototype typedef void (* ck_msg_func)( const Chuck_Msg * msg ); //----------------------------------------------------------------------------- // name: struct Chuck_Msg // desc: ... //----------------------------------------------------------------------------- struct Chuck_Msg { t_CKUINT type; t_CKUINT param; Chuck_VM_Code * code; Chuck_VM_Shred * shred; t_CKTIME when; void * user; ck_msg_func reply; t_CKUINT replyA; t_CKUINT replyB; void * replyC; std::vector * args; Chuck_Msg() { memset( this, 0, sizeof(*this) ); } ~Chuck_Msg() { SAFE_DELETE( args ); } void set( const std::vector & vargs ) { SAFE_DELETE(args); args = new std::vector; (*args) = vargs; } }; #endif chuck-1.2.0.8.dfsg/src/chuck_win32.c0000644000175000017500000044134210600421721015420 0ustar piempiem/* A Bison parser, made by GNU Bison 1.875b. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Written by Richard Stallman by simplifying the original so called ``semantic'' parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { ID = 258, STRING_LIT = 259, NUM = 260, FLOAT = 261, POUND = 262, COMMA = 263, COLON = 264, SEMICOLON = 265, LPAREN = 266, RPAREN = 267, LBRACK = 268, RBRACK = 269, LBRACE = 270, RBRACE = 271, DOT = 272, PLUS = 273, MINUS = 274, TIMES = 275, DIVIDE = 276, PERCENT = 277, EQ = 278, NEQ = 279, LT = 280, LE = 281, GT = 282, GE = 283, AND = 284, OR = 285, ASSIGN = 286, IF = 287, THEN = 288, ELSE = 289, WHILE = 290, FOR = 291, DO = 292, LOOP = 293, BREAK = 294, CONTINUE = 295, NULL_TOK = 296, FUNCTION = 297, RETURN = 298, QUESTION = 299, EXCLAMATION = 300, S_OR = 301, S_AND = 302, S_XOR = 303, PLUSPLUS = 304, MINUSMINUS = 305, DOLLAR = 306, SIMULT = 307, PATTERN = 308, CODE = 309, TRANSPORT = 310, HOST = 311, TIME = 312, WHENEVER = 313, NEXT = 314, UNTIL = 315, EVERY = 316, BEFORE = 317, AFTER = 318, AT = 319, AT_SYM = 320, ATAT_SYM = 321, NEW = 322, SIZEOF = 323, TYPEOF = 324, SAME = 325, PLUS_CHUCK = 326, MINUS_CHUCK = 327, TIMES_CHUCK = 328, DIVIDE_CHUCK = 329, S_AND_CHUCK = 330, S_OR_CHUCK = 331, S_XOR_CHUCK = 332, SHIFT_RIGHT_CHUCK = 333, SHIFT_LEFT_CHUCK = 334, PERCENT_CHUCK = 335, SHIFT_RIGHT = 336, SHIFT_LEFT = 337, TILDA = 338, CHUCK = 339, COLONCOLON = 340, S_CHUCK = 341, AT_CHUCK = 342, LEFT_S_CHUCK = 343, UNCHUCK = 344, CLASS = 345, INTERFACE = 346, EXTENDS = 347, IMPLEMENTS = 348, PUBLIC = 349, PROTECTED = 350, PRIVATE = 351, STATIC = 352, ABSTRACT = 353, CONST = 354, SPORK = 355, L_HACK = 356, R_HACK = 357 }; #endif #define ID 258 #define STRING_LIT 259 #define NUM 260 #define FLOAT 261 #define POUND 262 #define COMMA 263 #define COLON 264 #define SEMICOLON 265 #define LPAREN 266 #define RPAREN 267 #define LBRACK 268 #define RBRACK 269 #define LBRACE 270 #define RBRACE 271 #define DOT 272 #define PLUS 273 #define MINUS 274 #define TIMES 275 #define DIVIDE 276 #define PERCENT 277 #define EQ 278 #define NEQ 279 #define LT 280 #define LE 281 #define GT 282 #define GE 283 #define AND 284 #define OR 285 #define ASSIGN 286 #define IF 287 #define THEN 288 #define ELSE 289 #define WHILE 290 #define FOR 291 #define DO 292 #define LOOP 293 #define BREAK 294 #define CONTINUE 295 #define NULL_TOK 296 #define FUNCTION 297 #define RETURN 298 #define QUESTION 299 #define EXCLAMATION 300 #define S_OR 301 #define S_AND 302 #define S_XOR 303 #define PLUSPLUS 304 #define MINUSMINUS 305 #define DOLLAR 306 #define SIMULT 307 #define PATTERN 308 #define CODE 309 #define TRANSPORT 310 #define HOST 311 #define TIME 312 #define WHENEVER 313 #define NEXT 314 #define UNTIL 315 #define EVERY 316 #define BEFORE 317 #define AFTER 318 #define AT 319 #define AT_SYM 320 #define ATAT_SYM 321 #define NEW 322 #define SIZEOF 323 #define TYPEOF 324 #define SAME 325 #define PLUS_CHUCK 326 #define MINUS_CHUCK 327 #define TIMES_CHUCK 328 #define DIVIDE_CHUCK 329 #define S_AND_CHUCK 330 #define S_OR_CHUCK 331 #define S_XOR_CHUCK 332 #define SHIFT_RIGHT_CHUCK 333 #define SHIFT_LEFT_CHUCK 334 #define PERCENT_CHUCK 335 #define SHIFT_RIGHT 336 #define SHIFT_LEFT 337 #define TILDA 338 #define CHUCK 339 #define COLONCOLON 340 #define S_CHUCK 341 #define AT_CHUCK 342 #define LEFT_S_CHUCK 343 #define UNCHUCK 344 #define CLASS 345 #define INTERFACE 346 #define EXTENDS 347 #define IMPLEMENTS 348 #define PUBLIC 349 #define PROTECTED 350 #define PRIVATE 351 #define STATIC 352 #define ABSTRACT 353 #define CONST 354 #define SPORK 355 #define L_HACK 356 #define R_HACK 357 /* Copy the first part of user declarations. */ #line 1 "chuck.y" /*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck.tab.c // desc: chuck parser // // author: Ge Wang (gewang@cs.princeton.edu) - generated by yacc // Perry R. Cook (prc@cs.princeton.edu) // // based in part on the ansi C grammar by Jeff Lee, maintained by Jutta Degener // // date: Summer 2002 //----------------------------------------------------------------------------- #include #include #include #include "chuck_utils.h" #include "chuck_errmsg.h" #include "chuck_absyn.h" // function int yylex( void ); void yyerror( char *s ) { EM_error( EM_tokPos, "%s", s ); } a_Program g_program = NULL; /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 0 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 59 "chuck.y" typedef union YYSTYPE { int pos; int ival; double fval; c_str sval; a_Program program; a_Section program_section; a_Stmt_List stmt_list; a_Class_Def class_def; a_Class_Ext class_ext; a_Class_Body class_body; a_Stmt stmt; a_Exp exp; a_Func_Def func_def; a_Var_Decl_List var_decl_list; a_Var_Decl var_decl; a_Type_Decl type_decl; a_Arg_List arg_list; a_Id_List id_list; a_Array_Sub array_sub; } YYSTYPE; /* Line 191 of yacc.c. */ #line 359 "chuck.tab.c" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 214 of yacc.c. */ #line 371 "chuck.tab.c" #if ! defined (yyoverflow) || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # if YYSTACK_USE_ALLOCA # define YYSTACK_ALLOC alloca # else # ifndef YYSTACK_USE_ALLOCA # if defined (alloca) || defined (_ALLOCA_H) # define YYSTACK_ALLOC alloca # else # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # else # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif # define YYSTACK_ALLOC malloc # define YYSTACK_FREE free # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ register YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else typedef short yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 107 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 1128 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 103 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 53 /* YYNRULES -- Number of rules. */ #define YYNRULES 171 /* YYNRULES -- Number of states. */ #define YYNSTATES 295 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 357 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const unsigned char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const unsigned short yyprhs[] = { 0, 0, 3, 5, 8, 10, 12, 14, 21, 29, 36, 44, 47, 52, 55, 60, 62, 63, 65, 68, 70, 72, 74, 77, 79, 83, 85, 89, 98, 106, 115, 123, 125, 127, 128, 130, 132, 134, 136, 138, 140, 141, 143, 146, 150, 155, 157, 159, 161, 164, 167, 172, 174, 177, 179, 181, 183, 185, 187, 190, 194, 197, 200, 206, 214, 220, 228, 235, 243, 249, 257, 263, 266, 270, 272, 275, 277, 281, 283, 287, 291, 296, 299, 303, 305, 308, 312, 315, 319, 321, 325, 327, 330, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, 359, 361, 367, 369, 373, 375, 379, 381, 385, 387, 391, 393, 397, 399, 403, 407, 409, 413, 417, 421, 425, 427, 431, 435, 437, 441, 445, 447, 451, 455, 459, 461, 465, 467, 471, 473, 476, 479, 482, 485, 488, 491, 495, 499, 501, 503, 505, 507, 509, 512, 514, 518, 520, 523, 527, 532, 536, 539, 542, 544, 546, 548, 550, 552, 556, 560 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const short yyrhs[] = { 104, 0, -1, 105, -1, 105, 104, -1, 123, -1, 114, -1, 106, -1, 115, 90, 112, 15, 108, 16, -1, 115, 90, 112, 107, 15, 108, 16, -1, 115, 91, 112, 15, 108, 16, -1, 115, 91, 112, 111, 15, 108, 16, -1, 93, 112, -1, 93, 112, 92, 113, -1, 92, 113, -1, 92, 113, 93, 112, -1, 109, -1, -1, 110, -1, 110, 109, -1, 123, -1, 114, -1, 106, -1, 92, 112, -1, 3, -1, 3, 8, 112, -1, 3, -1, 3, 17, 113, -1, 116, 117, 121, 3, 11, 122, 12, 128, -1, 116, 117, 121, 3, 11, 12, 128, -1, 116, 117, 121, 3, 11, 122, 12, 10, -1, 116, 117, 121, 3, 11, 12, 10, -1, 94, -1, 96, -1, -1, 42, -1, 94, -1, 95, -1, 96, -1, 97, -1, 98, -1, -1, 3, -1, 3, 65, -1, 25, 113, 27, -1, 25, 113, 27, 65, -1, 118, -1, 119, -1, 120, -1, 120, 133, -1, 120, 136, -1, 120, 136, 8, 122, -1, 124, -1, 124, 123, -1, 129, -1, 127, -1, 126, -1, 125, -1, 128, -1, 43, 10, -1, 43, 130, 10, -1, 39, 10, -1, 40, 10, -1, 32, 11, 130, 12, 124, -1, 32, 11, 130, 12, 124, 34, 124, -1, 35, 11, 130, 12, 124, -1, 37, 124, 35, 11, 130, 12, 10, -1, 36, 11, 129, 129, 12, 124, -1, 36, 11, 129, 129, 130, 12, 124, -1, 60, 11, 130, 12, 124, -1, 37, 124, 60, 11, 130, 12, 10, -1, 38, 11, 130, 12, 124, -1, 15, 16, -1, 15, 123, 16, -1, 10, -1, 130, 10, -1, 131, -1, 131, 8, 130, -1, 134, -1, 131, 137, 134, -1, 13, 130, 14, -1, 13, 130, 14, 132, -1, 13, 14, -1, 133, 13, 14, -1, 138, -1, 120, 135, -1, 97, 120, 135, -1, 70, 135, -1, 97, 70, 135, -1, 136, -1, 136, 8, 135, -1, 3, -1, 3, 132, -1, 3, 133, -1, 84, -1, 87, -1, 71, -1, 72, -1, 73, -1, 74, -1, 78, -1, 79, -1, 80, -1, 89, -1, 75, -1, 76, -1, 77, -1, 139, -1, 139, 44, 130, 9, 138, -1, 140, -1, 139, 30, 140, -1, 141, -1, 140, 29, 141, -1, 142, -1, 141, 46, 142, -1, 143, -1, 142, 48, 143, -1, 144, -1, 143, 47, 144, -1, 145, -1, 144, 23, 145, -1, 144, 24, 145, -1, 146, -1, 145, 25, 146, -1, 145, 27, 146, -1, 145, 26, 146, -1, 145, 28, 146, -1, 147, -1, 146, 82, 147, -1, 146, 81, 147, -1, 148, -1, 147, 18, 148, -1, 147, 19, 148, -1, 149, -1, 148, 20, 149, -1, 148, 21, 149, -1, 148, 22, 149, -1, 150, -1, 149, 83, 150, -1, 151, -1, 150, 51, 120, -1, 153, -1, 49, 151, -1, 50, 151, -1, 152, 151, -1, 69, 151, -1, 68, 151, -1, 67, 120, -1, 67, 120, 132, -1, 100, 83, 128, -1, 18, -1, 19, -1, 83, -1, 45, -1, 20, -1, 100, 83, -1, 154, -1, 153, 85, 154, -1, 155, -1, 154, 132, -1, 154, 11, 12, -1, 154, 11, 130, 12, -1, 154, 17, 3, -1, 154, 49, -1, 154, 50, -1, 3, -1, 5, -1, 6, -1, 4, -1, 132, -1, 101, 130, 102, -1, 11, 130, 12, -1, 11, 12, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short yyrline[] = { 0, 171, 171, 172, 176, 177, 178, 182, 184, 186, 188, 193, 194, 195, 196, 200, 201, 205, 206, 211, 212, 213, 217, 221, 222, 226, 227, 231, 233, 235, 237, 242, 243, 244, 248, 249, 250, 251, 255, 256, 257, 261, 262, 266, 267, 276, 277, 282, 283, 287, 288, 292, 293, 297, 298, 299, 300, 302, 306, 307, 308, 309, 313, 315, 320, 322, 324, 326, 328, 330, 332, 337, 338, 342, 343, 347, 348, 352, 353, 358, 359, 364, 365, 369, 370, 371, 372, 373, 377, 378, 382, 383, 384, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 404, 405, 410, 411, 416, 417, 422, 423, 428, 429, 434, 435, 440, 441, 443, 448, 449, 451, 453, 455, 460, 461, 463, 468, 469, 471, 476, 477, 479, 481, 486, 487, 492, 493, 498, 499, 501, 503, 505, 507, 509, 511, 513, 518, 519, 520, 521, 522, 523, 528, 529, 534, 535, 537, 539, 541, 543, 545, 550, 551, 552, 553, 554, 555, 556, 557 }; #endif #if YYDEBUG || YYERROR_VERBOSE /* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "ID", "STRING_LIT", "NUM", "FLOAT", "POUND", "COMMA", "COLON", "SEMICOLON", "LPAREN", "RPAREN", "LBRACK", "RBRACK", "LBRACE", "RBRACE", "DOT", "PLUS", "MINUS", "TIMES", "DIVIDE", "PERCENT", "EQ", "NEQ", "LT", "LE", "GT", "GE", "AND", "OR", "ASSIGN", "IF", "THEN", "ELSE", "WHILE", "FOR", "DO", "LOOP", "BREAK", "CONTINUE", "NULL_TOK", "FUNCTION", "RETURN", "QUESTION", "EXCLAMATION", "S_OR", "S_AND", "S_XOR", "PLUSPLUS", "MINUSMINUS", "DOLLAR", "SIMULT", "PATTERN", "CODE", "TRANSPORT", "HOST", "TIME", "WHENEVER", "NEXT", "UNTIL", "EVERY", "BEFORE", "AFTER", "AT", "AT_SYM", "ATAT_SYM", "NEW", "SIZEOF", "TYPEOF", "SAME", "PLUS_CHUCK", "MINUS_CHUCK", "TIMES_CHUCK", "DIVIDE_CHUCK", "S_AND_CHUCK", "S_OR_CHUCK", "S_XOR_CHUCK", "SHIFT_RIGHT_CHUCK", "SHIFT_LEFT_CHUCK", "PERCENT_CHUCK", "SHIFT_RIGHT", "SHIFT_LEFT", "TILDA", "CHUCK", "COLONCOLON", "S_CHUCK", "AT_CHUCK", "LEFT_S_CHUCK", "UNCHUCK", "CLASS", "INTERFACE", "EXTENDS", "IMPLEMENTS", "PUBLIC", "PROTECTED", "PRIVATE", "STATIC", "ABSTRACT", "CONST", "SPORK", "L_HACK", "R_HACK", "$accept", "program", "program_section", "class_definition", "class_ext", "class_body", "class_body2", "class_section", "iface_ext", "id_list", "id_dot", "function_definition", "class_decl", "function_decl", "static_decl", "type_decl_a", "type_decl_b", "type_decl", "type_decl2", "arg_list", "statement_list", "statement", "jump_statement", "selection_statement", "loop_statement", "code_segment", "expression_statement", "expression", "chuck_expression", "array_exp", "array_empty", "decl_expression", "var_decl_list", "var_decl", "chuck_operator", "conditional_expression", "logical_or_expression", "logical_and_expression", "inclusive_or_expression", "exclusive_or_expression", "and_expression", "equality_expression", "relational_expression", "shift_expression", "additive_expression", "multiplicative_expression", "tilda_expression", "cast_expression", "unary_expression", "unary_operator", "dur_expression", "postfix_expression", "primary_expression", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const unsigned short yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { 0, 103, 104, 104, 105, 105, 105, 106, 106, 106, 106, 107, 107, 107, 107, 108, 108, 109, 109, 110, 110, 110, 111, 112, 112, 113, 113, 114, 114, 114, 114, 115, 115, 115, 116, 116, 116, 116, 117, 117, 117, 118, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 124, 124, 124, 125, 125, 125, 125, 126, 126, 127, 127, 127, 127, 127, 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133, 134, 134, 134, 134, 134, 135, 135, 136, 136, 136, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141, 142, 142, 143, 143, 144, 144, 144, 145, 145, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 148, 149, 149, 150, 150, 151, 151, 151, 151, 151, 151, 151, 151, 151, 152, 152, 152, 152, 152, 152, 153, 153, 154, 154, 154, 154, 154, 154, 154, 155, 155, 155, 155, 155, 155, 155, 155 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { 0, 2, 1, 2, 1, 1, 1, 6, 7, 6, 7, 2, 4, 2, 4, 1, 0, 1, 2, 1, 1, 1, 2, 1, 3, 1, 3, 8, 7, 8, 7, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 2, 3, 4, 1, 1, 1, 2, 2, 4, 1, 2, 1, 1, 1, 1, 1, 2, 3, 2, 2, 5, 7, 5, 7, 6, 7, 5, 7, 5, 2, 3, 1, 2, 1, 3, 1, 3, 3, 4, 2, 3, 1, 2, 3, 2, 3, 1, 3, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 1, 3, 3, 3, 1, 3, 1, 3, 1, 2, 2, 2, 2, 2, 2, 3, 3, 1, 1, 1, 1, 1, 2, 1, 3, 1, 2, 3, 4, 3, 2, 2, 1, 1, 1, 1, 1, 3, 3, 2 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const unsigned char yydefact[] = { 33, 164, 167, 165, 166, 73, 0, 0, 0, 149, 150, 153, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 152, 0, 0, 0, 0, 0, 0, 0, 151, 35, 36, 37, 0, 0, 0, 0, 33, 6, 5, 0, 40, 45, 46, 0, 4, 51, 56, 55, 54, 57, 53, 0, 75, 168, 77, 83, 106, 108, 110, 112, 114, 116, 118, 121, 126, 129, 132, 136, 138, 0, 140, 155, 157, 42, 171, 0, 0, 71, 0, 25, 0, 0, 0, 0, 0, 0, 60, 61, 58, 0, 164, 141, 142, 0, 41, 146, 145, 144, 90, 86, 88, 0, 0, 154, 0, 1, 3, 0, 0, 38, 39, 0, 84, 52, 74, 0, 95, 96, 97, 98, 103, 104, 105, 99, 100, 101, 93, 94, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, 162, 163, 158, 170, 79, 72, 0, 43, 0, 0, 0, 0, 0, 0, 59, 0, 147, 0, 91, 92, 0, 87, 85, 148, 169, 23, 0, 0, 47, 0, 76, 78, 109, 0, 111, 113, 115, 117, 119, 120, 122, 124, 123, 125, 128, 127, 130, 131, 133, 134, 135, 137, 139, 156, 159, 0, 161, 80, 26, 44, 0, 0, 0, 0, 0, 0, 0, 81, 0, 89, 0, 33, 0, 0, 0, 33, 0, 0, 0, 48, 0, 0, 160, 62, 64, 0, 0, 0, 0, 70, 68, 82, 24, 21, 0, 15, 33, 20, 19, 13, 11, 33, 0, 22, 33, 0, 107, 0, 66, 0, 0, 0, 7, 18, 0, 0, 0, 9, 0, 0, 0, 0, 63, 67, 65, 69, 14, 12, 8, 10, 30, 28, 49, 0, 0, 29, 27, 50 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short yydefgoto[] = { -1, 37, 38, 250, 231, 251, 252, 253, 234, 183, 82, 254, 41, 42, 113, 43, 44, 45, 186, 278, 255, 47, 48, 49, 50, 51, 52, 53, 54, 55, 176, 56, 101, 102, 131, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -188 static const short yypact[] = { 532, 13, -188, -188, -188, -188, 36, 1027, 631, -188, -188, -188, 16, 25, 49, 51, 702, 57, 60, 67, -188, 755, -188, 96, 96, 86, 32, 96, 96, 20, -188, -40, -188, 33, 19, 55, 1027, 43, 235, -188, -188, 44, 59, -188, -188, 20, -188, 702, -188, -188, -188, -188, -188, 107, 236, -188, -188, -188, 23, 98, 94, 114, 95, 135, 122, 79, 149, 90, 61, 118, -188, 96, 93, 71, -188, -188, -188, 168, 167, -188, 166, 169, 156, 1027, 1027, 808, -8, 1027, -188, -188, -188, 174, -188, -188, -188, 1027, 120, 175, -188, -188, 177, -188, 179, 20, 20, 176, 91, -188, -188, 189, 189, -188, -188, 32, -188, -188, -188, 1027, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 1027, 96, 1027, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 32, -188, 7, 861, 191, -188, -188, -188, -188, 175, -188, 16, 130, 186, 187, 808, 190, 193, 188, -188, 194, -188, 921, -188, 192, 20, -188, -188, -188, -188, 201, 0, 6, 197, 208, -188, -188, 98, 203, 94, 114, 95, 135, 122, 122, 79, 79, 79, 79, 149, 149, 90, 90, 61, 61, 61, 118, -188, 71, -188, 202, -188, -188, -188, -188, 702, 702, 974, 1027, 1027, 702, 702, -188, 199, -188, 189, 334, 16, 189, 204, 334, 189, 205, 207, 192, 211, 96, -188, 184, -188, 702, 212, 213, 214, -188, -188, -188, -188, -188, 215, -188, 433, -188, -188, 136, 131, 334, 216, -188, 334, 34, -188, 702, -188, 702, 218, 220, -188, -188, 189, 16, 217, -188, 221, 48, 20, 222, -188, -188, -188, -188, -188, -188, -188, -188, -188, -188, 234, 80, 32, -188, -188, -188 }; /* YYPGOTO[NTERM-NUM]. */ static const short yypgoto[] = { -188, 209, -188, 31, -188, -187, -10, -188, -188, -105, -154, 38, -188, -188, -188, -188, -188, -26, -188, -39, 26, -15, -188, -188, -188, -101, -71, -4, -188, -67, 72, 125, -38, -19, -188, 21, -188, 129, 128, 133, 127, 132, 35, 12, 27, 30, -18, 113, 1, -188, -188, 112, -188 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -42 static const short yytable[] = { 97, 86, 77, 78, 180, 184, 159, 114, 104, 215, 92, 2, 3, 4, 167, 228, -41, 91, 6, 81, 7, 232, 96, 100, 93, 94, 46, 168, 98, 99, 173, 39, 106, 175, 80, 96, 83, 96, 40, 1, 2, 3, 4, 107, 12, 259, 276, 6, 76, 7, -31, -31, 169, 132, 9, 10, 11, 12, 287, 12, 84, 12, 85, 8, 46, 178, 179, 133, 87, 39, 88, 273, 153, 115, 275, 256, 40, 89, 75, 165, 166, 22, 155, 170, 7, 23, 24, 185, 156, 103, 292, 172, 229, 230, 214, 8, 219, 95, 233, 92, 2, 3, 4, 26, 27, 28, 29, 6, 36, 7, 148, 149, 150, 187, 9, 10, 11, 116, 284, 30, 157, 158, 249, -32, -32, 257, 209, 134, 260, 190, 205, 206, 207, 34, 109, 110, 35, 36, 105, 226, 135, 22, 137, 159, 151, 23, 24, 140, 141, 142, 143, 212, 197, 198, 199, 200, 111, 112, 138, 139, 144, 145, 136, 26, 27, 28, 283, 146, 147, 152, 78, 201, 202, 195, 196, 288, 203, 204, 154, 30, 160, 161, 162, 164, 171, 75, 163, 177, 7, 293, 174, 8, 182, 181, 213, 216, 35, 36, 217, 218, 222, 220, 240, 241, 221, 225, 223, 246, 247, 227, 235, 237, 238, 248, 239, 243, 244, 245, 264, 258, 261, 224, 262, 272, 266, 267, 268, 265, 281, 271, 282, 269, 274, 285, 290, -2, 277, 286, 1, 2, 3, 4, 291, 270, 117, 5, 6, 108, 7, 279, 8, 280, 294, 9, 10, 11, 188, 236, 289, 263, 12, 189, 191, 193, 208, 277, 210, 13, 192, 194, 14, 15, 16, 17, 18, 19, 0, 20, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 0, 30, 0, 128, 0, 0, 129, 0, 130, 0, 0, 0, 31, 32, 33, 34, 0, 0, 35, 36, 1, 2, 3, 4, 0, 0, 0, 5, 6, 0, 7, 0, 8, -16, 0, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 0, 20, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, 34, 0, 0, 35, 36, 1, 2, 3, 4, 0, 0, 0, 5, 6, 0, 7, 0, 8, -17, 0, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 0, 20, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, 34, 0, 0, 35, 36, 1, 2, 3, 4, 0, 0, 0, 5, 6, 0, 7, 0, 8, 0, 0, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 0, 20, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 32, 33, 34, 0, 0, 35, 36, 1, 2, 3, 4, 0, 0, 0, 5, 6, 0, 7, 0, 8, 79, 0, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 0, 0, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 6, 30, 7, 0, 8, 0, 0, 9, 10, 11, 0, 0, 0, 0, 12, 34, 0, 0, 35, 36, 0, 13, 0, 0, 14, 15, 16, 17, 18, 19, 0, 0, 21, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 1, 2, 3, 4, 25, 0, 0, 90, 6, 0, 7, 26, 27, 28, 29, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 0, 35, 36, 23, 24, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 5, 6, 0, 7, 26, 27, 28, 29, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 0, 35, 36, 23, 24, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 6, 211, 7, 26, 27, 28, 29, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 0, 35, 36, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 26, 27, 28, 29, 6, 0, 7, 224, 0, 0, 0, 9, 10, 11, 0, 0, 30, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, 36, 0, 0, 0, 22, 0, 0, 0, 23, 24, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 6, 242, 7, 26, 27, 28, 29, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 0, 35, 36, 23, 24, 0, 0, 0, 0, 0, 1, 2, 3, 4, 0, 0, 0, 0, 6, 0, 7, 26, 27, 28, 29, 9, 10, 11, 0, 0, 0, 0, 12, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 22, 0, 35, 36, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 0, 0, 35, 36 }; static const short yycheck[] = { 26, 16, 6, 7, 105, 110, 73, 45, 34, 163, 3, 4, 5, 6, 85, 15, 3, 21, 11, 3, 13, 15, 3, 3, 23, 24, 0, 35, 27, 28, 97, 0, 36, 100, 8, 3, 11, 3, 0, 3, 4, 5, 6, 0, 25, 232, 12, 11, 12, 13, 90, 91, 60, 30, 18, 19, 20, 25, 10, 25, 11, 25, 11, 15, 38, 103, 104, 44, 11, 38, 10, 258, 71, 47, 261, 229, 38, 10, 65, 83, 84, 45, 11, 87, 13, 49, 50, 113, 17, 70, 10, 95, 92, 93, 161, 15, 167, 11, 92, 3, 4, 5, 6, 67, 68, 69, 70, 11, 101, 13, 20, 21, 22, 117, 18, 19, 20, 10, 272, 83, 49, 50, 227, 90, 91, 230, 152, 29, 233, 133, 148, 149, 150, 97, 90, 91, 100, 101, 83, 177, 46, 45, 47, 210, 83, 49, 50, 25, 26, 27, 28, 155, 140, 141, 142, 143, 97, 98, 23, 24, 81, 82, 48, 67, 68, 69, 271, 18, 19, 51, 174, 144, 145, 138, 139, 276, 146, 147, 85, 83, 12, 14, 16, 27, 10, 65, 17, 8, 13, 290, 13, 15, 3, 102, 3, 65, 100, 101, 12, 12, 12, 11, 217, 218, 11, 13, 12, 222, 223, 8, 13, 3, 9, 14, 12, 219, 220, 221, 34, 15, 15, 14, 11, 92, 12, 12, 12, 242, 10, 93, 10, 16, 16, 16, 12, 0, 262, 16, 3, 4, 5, 6, 8, 253, 8, 10, 11, 38, 13, 264, 15, 266, 291, 18, 19, 20, 131, 185, 277, 238, 25, 132, 134, 136, 151, 291, 154, 32, 135, 137, 35, 36, 37, 38, 39, 40, -1, 42, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, -1, 83, -1, 84, -1, -1, 87, -1, 89, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, 101, 3, 4, 5, 6, -1, -1, -1, 10, 11, -1, 13, -1, 15, 16, -1, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, 32, -1, -1, 35, 36, 37, 38, 39, 40, -1, 42, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, 101, 3, 4, 5, 6, -1, -1, -1, 10, 11, -1, 13, -1, 15, 16, -1, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, 32, -1, -1, 35, 36, 37, 38, 39, 40, -1, 42, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, 101, 3, 4, 5, 6, -1, -1, -1, 10, 11, -1, 13, -1, 15, -1, -1, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, 32, -1, -1, 35, 36, 37, 38, 39, 40, -1, 42, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 94, 95, 96, 97, -1, -1, 100, 101, 3, 4, 5, 6, -1, -1, -1, 10, 11, -1, 13, -1, 15, 16, -1, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, -1, -1, 32, -1, -1, 35, 36, 37, 38, 39, 40, -1, -1, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, 60, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, 10, 11, 83, 13, -1, 15, -1, -1, 18, 19, 20, -1, -1, -1, -1, 25, 97, -1, -1, 100, 101, -1, 32, -1, -1, 35, 36, 37, 38, 39, 40, -1, -1, 43, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, 3, 4, 5, 6, 60, -1, -1, 10, 11, -1, 13, 67, 68, 69, 70, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 45, -1, 100, 101, 49, 50, -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, 10, 11, -1, 13, 67, 68, 69, 70, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 45, -1, 100, 101, 49, 50, -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 11, 12, 13, 67, 68, 69, 70, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 45, -1, 100, 101, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, 67, 68, 69, 70, 11, -1, 13, 14, -1, -1, -1, 18, 19, 20, -1, -1, 83, -1, 25, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, 100, 101, -1, -1, -1, 45, -1, -1, -1, 49, 50, -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 11, 12, 13, 67, 68, 69, 70, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 45, -1, 100, 101, 49, 50, -1, -1, -1, -1, -1, 3, 4, 5, 6, -1, -1, -1, -1, 11, -1, 13, 67, 68, 69, 70, 18, 19, 20, -1, -1, -1, -1, 25, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, 45, -1, 100, 101, 49, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 67, 68, 69, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 83, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 97, -1, -1, 100, 101 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { 0, 3, 4, 5, 6, 10, 11, 13, 15, 18, 19, 20, 25, 32, 35, 36, 37, 38, 39, 40, 42, 43, 45, 49, 50, 60, 67, 68, 69, 70, 83, 94, 95, 96, 97, 100, 101, 104, 105, 106, 114, 115, 116, 118, 119, 120, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 134, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 65, 12, 130, 130, 16, 123, 3, 113, 11, 11, 11, 124, 11, 10, 10, 10, 130, 3, 151, 151, 11, 3, 120, 151, 151, 3, 135, 136, 70, 120, 83, 130, 0, 104, 90, 91, 97, 98, 117, 135, 123, 10, 8, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 84, 87, 89, 137, 30, 44, 29, 46, 48, 47, 23, 24, 25, 26, 27, 28, 81, 82, 18, 19, 20, 21, 22, 83, 51, 151, 85, 11, 17, 49, 50, 132, 12, 14, 16, 17, 27, 130, 130, 129, 35, 60, 130, 10, 130, 132, 13, 132, 133, 8, 135, 135, 128, 102, 3, 112, 112, 120, 121, 130, 134, 140, 130, 141, 142, 143, 144, 145, 145, 146, 146, 146, 146, 147, 147, 148, 148, 149, 149, 149, 150, 120, 154, 12, 130, 3, 132, 113, 65, 12, 12, 129, 11, 11, 12, 12, 14, 13, 135, 8, 15, 92, 93, 107, 15, 92, 111, 13, 133, 3, 9, 12, 124, 124, 12, 130, 130, 130, 124, 124, 14, 112, 106, 108, 109, 110, 114, 123, 113, 112, 15, 108, 112, 15, 11, 138, 34, 124, 12, 12, 12, 16, 109, 93, 92, 108, 16, 108, 12, 120, 122, 124, 124, 10, 10, 112, 113, 16, 16, 10, 128, 136, 12, 8, 10, 128, 122 }; #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t # endif #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrlab1 /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror ("syntax error: cannot back up");\ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Compute the default location (before the actions are run). */ #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ Current.first_line = Rhs[1].first_line; \ Current.first_column = Rhs[1].first_column; \ Current.last_line = Rhs[N].last_line; \ Current.last_column = Rhs[N].last_column; #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) # define YYDSYMPRINT(Args) \ do { \ if (yydebug) \ yysymprint Args; \ } while (0) # define YYDSYMPRINTF(Title, Token, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ Token, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (cinluded). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_stack_print (short *bottom, short *top) #else static void yy_stack_print (bottom, top) short *bottom; short *top; #endif { YYFPRINTF (stderr, "Stack now"); for (/* Nothing. */; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_reduce_print (int yyrule) #else static void yy_reduce_print (yyrule) int yyrule; #endif { int yyi; unsigned int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YYDSYMPRINT(Args) # define YYDSYMPRINTF(Title, Token, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #if YYMAXDEPTH == 0 # undef YYMAXDEPTH #endif #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { register const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { register char *yyd = yydest; register const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif #endif /* !YYERROR_VERBOSE */ #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else static void yysymprint (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; if (yytype < YYNTOKENS) { YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); # ifdef YYPRINT YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif } else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); switch (yytype) { default: break; } YYFPRINTF (yyoutput, ")"); } #endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yydestruct (int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yytype, yyvaluep) int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM); # else int yyparse (); # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ /* The lookahead symbol. */ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM) # else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void) #else int yyparse () #endif #endif { register int yystate; register int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Lookahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short yyssa[YYINITDEPTH]; short *yyss = yyssa; register short *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; register YYSTYPE *yyvsp; #define YYPOPSTACK (yyvsp--, yyssp--) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow ("parser stack overflow", &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyoverflowlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyoverflowlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { short *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyoverflowlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a lookahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YYDSYMPRINTF ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Shift the lookahead token. */ YYDPRINTF ((stderr, "Shifting token %s, ", yytname[yytoken])); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 2: #line 171 "chuck.y" { yyval.program = g_program = new_program( yyvsp[0].program_section, EM_lineNum ); ;} break; case 3: #line 172 "chuck.y" { yyval.program = g_program = prepend_program( yyvsp[-1].program_section, yyvsp[0].program, EM_lineNum ); ;} break; case 4: #line 176 "chuck.y" { yyval.program_section = new_section_stmt( yyvsp[0].stmt_list, EM_lineNum ); ;} break; case 5: #line 177 "chuck.y" { yyval.program_section = new_section_func_def( yyvsp[0].func_def, EM_lineNum ); ;} break; case 6: #line 178 "chuck.y" { yyval.program_section = new_section_class_def( yyvsp[0].class_def, EM_lineNum ); ;} break; case 7: #line 183 "chuck.y" { yyval.class_def = new_class_def( yyvsp[-5].ival, yyvsp[-3].id_list, NULL, yyvsp[-1].class_body, EM_lineNum ); ;} break; case 8: #line 185 "chuck.y" { yyval.class_def = new_class_def( yyvsp[-6].ival, yyvsp[-4].id_list, yyvsp[-3].class_ext, yyvsp[-1].class_body, EM_lineNum ); ;} break; case 9: #line 187 "chuck.y" { yyval.class_def = new_iface_def( yyvsp[-5].ival, yyvsp[-3].id_list, NULL, yyvsp[-1].class_body, EM_lineNum ); ;} break; case 10: #line 189 "chuck.y" { yyval.class_def = new_iface_def( yyvsp[-6].ival, yyvsp[-4].id_list, yyvsp[-3].class_ext, yyvsp[-1].class_body, EM_lineNum ); ;} break; case 11: #line 193 "chuck.y" { yyval.class_ext = new_class_ext( NULL, yyvsp[0].id_list, EM_lineNum ); ;} break; case 12: #line 194 "chuck.y" { yyval.class_ext = new_class_ext( yyvsp[0].id_list, yyvsp[-2].id_list, EM_lineNum ); ;} break; case 13: #line 195 "chuck.y" { yyval.class_ext = new_class_ext( yyvsp[0].id_list, NULL, EM_lineNum ); ;} break; case 14: #line 196 "chuck.y" { yyval.class_ext = new_class_ext( yyvsp[-2].id_list, yyvsp[0].id_list, EM_lineNum ); ;} break; case 15: #line 200 "chuck.y" { yyval.class_body = yyvsp[0].class_body; ;} break; case 16: #line 201 "chuck.y" { yyval.class_body = NULL; ;} break; case 17: #line 205 "chuck.y" { yyval.class_body = new_class_body( yyvsp[0].program_section, EM_lineNum ); ;} break; case 18: #line 206 "chuck.y" { yyval.class_body = prepend_class_body( yyvsp[-1].program_section, yyvsp[0].class_body, EM_lineNum ); ;} break; case 19: #line 211 "chuck.y" { yyval.program_section = new_section_stmt( yyvsp[0].stmt_list, EM_lineNum ); ;} break; case 20: #line 212 "chuck.y" { yyval.program_section = new_section_func_def( yyvsp[0].func_def, EM_lineNum ); ;} break; case 21: #line 213 "chuck.y" { yyval.program_section = new_section_class_def( yyvsp[0].class_def, EM_lineNum ); ;} break; case 22: #line 217 "chuck.y" { yyval.class_ext = new_class_ext( NULL, yyvsp[0].id_list, EM_lineNum ); ;} break; case 23: #line 221 "chuck.y" { yyval.id_list = new_id_list( yyvsp[0].sval, EM_lineNum ); ;} break; case 24: #line 222 "chuck.y" { yyval.id_list = prepend_id_list( yyvsp[-2].sval, yyvsp[0].id_list, EM_lineNum ); ;} break; case 25: #line 226 "chuck.y" { yyval.id_list = new_id_list( yyvsp[0].sval, EM_lineNum ); ;} break; case 26: #line 227 "chuck.y" { yyval.id_list = prepend_id_list( yyvsp[-2].sval, yyvsp[0].id_list, EM_lineNum ); ;} break; case 27: #line 232 "chuck.y" { yyval.func_def = new_func_def( yyvsp[-7].ival, yyvsp[-6].ival, yyvsp[-5].type_decl, yyvsp[-4].sval, yyvsp[-2].arg_list, yyvsp[0].stmt, EM_lineNum ); ;} break; case 28: #line 234 "chuck.y" { yyval.func_def = new_func_def( yyvsp[-6].ival, yyvsp[-5].ival, yyvsp[-4].type_decl, yyvsp[-3].sval, NULL, yyvsp[0].stmt, EM_lineNum ); ;} break; case 29: #line 236 "chuck.y" { yyval.func_def = new_func_def( yyvsp[-7].ival, yyvsp[-6].ival, yyvsp[-5].type_decl, yyvsp[-4].sval, yyvsp[-2].arg_list, NULL, EM_lineNum ); ;} break; case 30: #line 238 "chuck.y" { yyval.func_def = new_func_def( yyvsp[-6].ival, yyvsp[-5].ival, yyvsp[-4].type_decl, yyvsp[-3].sval, NULL, NULL, EM_lineNum ); ;} break; case 31: #line 242 "chuck.y" { yyval.ival = ae_key_public; ;} break; case 32: #line 243 "chuck.y" { yyval.ival = ae_key_private; ;} break; case 33: #line 244 "chuck.y" { yyval.ival = ae_key_private; ;} break; case 34: #line 248 "chuck.y" { yyval.ival = ae_key_func; ;} break; case 35: #line 249 "chuck.y" { yyval.ival = ae_key_public; ;} break; case 36: #line 250 "chuck.y" { yyval.ival = ae_key_protected; ;} break; case 37: #line 251 "chuck.y" { yyval.ival = ae_key_private; ;} break; case 38: #line 255 "chuck.y" { yyval.ival = ae_key_static; ;} break; case 39: #line 256 "chuck.y" { yyval.ival = ae_key_abstract; ;} break; case 40: #line 257 "chuck.y" { yyval.ival = ae_key_instance; ;} break; case 41: #line 261 "chuck.y" { yyval.type_decl = new_type_decl( new_id_list( yyvsp[0].sval, EM_lineNum ), 0, EM_lineNum ); ;} break; case 42: #line 262 "chuck.y" { yyval.type_decl = new_type_decl( new_id_list( yyvsp[-1].sval, EM_lineNum ), 1, EM_lineNum ); ;} break; case 43: #line 266 "chuck.y" { yyval.type_decl = new_type_decl( yyvsp[-1].id_list, 0, EM_lineNum ); ;} break; case 44: #line 267 "chuck.y" { yyval.type_decl = new_type_decl( yyvsp[-2].id_list, 1, EM_lineNum ); ;} break; case 45: #line 276 "chuck.y" { yyval.type_decl = yyvsp[0].type_decl; ;} break; case 46: #line 277 "chuck.y" { yyval.type_decl = yyvsp[0].type_decl; ;} break; case 47: #line 282 "chuck.y" { yyval.type_decl = yyvsp[0].type_decl; ;} break; case 48: #line 283 "chuck.y" { yyval.type_decl = add_type_decl_array( yyvsp[-1].type_decl, yyvsp[0].array_sub, EM_lineNum ); ;} break; case 49: #line 287 "chuck.y" { yyval.arg_list = new_arg_list( yyvsp[-1].type_decl, yyvsp[0].var_decl, EM_lineNum ); ;} break; case 50: #line 288 "chuck.y" { yyval.arg_list = prepend_arg_list( yyvsp[-3].type_decl, yyvsp[-2].var_decl, yyvsp[0].arg_list, EM_lineNum ); ;} break; case 51: #line 292 "chuck.y" { yyval.stmt_list = new_stmt_list( yyvsp[0].stmt, EM_lineNum ); ;} break; case 52: #line 293 "chuck.y" { yyval.stmt_list = prepend_stmt_list( yyvsp[-1].stmt, yyvsp[0].stmt_list, EM_lineNum ); ;} break; case 53: #line 297 "chuck.y" { yyval.stmt = yyvsp[0].stmt; ;} break; case 54: #line 298 "chuck.y" { yyval.stmt = yyvsp[0].stmt; ;} break; case 55: #line 299 "chuck.y" { yyval.stmt = yyvsp[0].stmt; ;} break; case 56: #line 300 "chuck.y" { yyval.stmt = yyvsp[0].stmt; ;} break; case 57: #line 302 "chuck.y" { yyval.stmt = yyvsp[0].stmt; ;} break; case 58: #line 306 "chuck.y" { yyval.stmt = new_stmt_from_return( NULL, EM_lineNum ); ;} break; case 59: #line 307 "chuck.y" { yyval.stmt = new_stmt_from_return( yyvsp[-1].exp, EM_lineNum ); ;} break; case 60: #line 308 "chuck.y" { yyval.stmt = new_stmt_from_break( EM_lineNum ); ;} break; case 61: #line 309 "chuck.y" { yyval.stmt = new_stmt_from_continue( EM_lineNum ); ;} break; case 62: #line 314 "chuck.y" { yyval.stmt = new_stmt_from_if( yyvsp[-2].exp, yyvsp[0].stmt, NULL, EM_lineNum ); ;} break; case 63: #line 316 "chuck.y" { yyval.stmt = new_stmt_from_if( yyvsp[-4].exp, yyvsp[-2].stmt, yyvsp[0].stmt, EM_lineNum ); ;} break; case 64: #line 321 "chuck.y" { yyval.stmt = new_stmt_from_while( yyvsp[-2].exp, yyvsp[0].stmt, EM_lineNum ); ;} break; case 65: #line 323 "chuck.y" { yyval.stmt = new_stmt_from_do_while( yyvsp[-2].exp, yyvsp[-5].stmt, EM_lineNum ); ;} break; case 66: #line 325 "chuck.y" { yyval.stmt = new_stmt_from_for( yyvsp[-3].stmt, yyvsp[-2].stmt, NULL, yyvsp[0].stmt, EM_lineNum ); ;} break; case 67: #line 327 "chuck.y" { yyval.stmt = new_stmt_from_for( yyvsp[-4].stmt, yyvsp[-3].stmt, yyvsp[-2].exp, yyvsp[0].stmt, EM_lineNum ); ;} break; case 68: #line 329 "chuck.y" { yyval.stmt = new_stmt_from_until( yyvsp[-2].exp, yyvsp[0].stmt, EM_lineNum ); ;} break; case 69: #line 331 "chuck.y" { yyval.stmt = new_stmt_from_do_until( yyvsp[-2].exp, yyvsp[-5].stmt, EM_lineNum ); ;} break; case 70: #line 333 "chuck.y" { yyval.stmt = new_stmt_from_loop( yyvsp[-2].exp, yyvsp[0].stmt, EM_lineNum ); ;} break; case 71: #line 337 "chuck.y" { yyval.stmt = new_stmt_from_code( NULL, EM_lineNum ); ;} break; case 72: #line 338 "chuck.y" { yyval.stmt = new_stmt_from_code( yyvsp[-1].stmt_list, EM_lineNum ); ;} break; case 73: #line 342 "chuck.y" { yyval.stmt = NULL; ;} break; case 74: #line 343 "chuck.y" { yyval.stmt = new_stmt_from_expression( yyvsp[-1].exp, EM_lineNum ); ;} break; case 75: #line 347 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 76: #line 348 "chuck.y" { yyval.exp = prepend_expression( yyvsp[-2].exp, yyvsp[0].exp, EM_lineNum ); ;} break; case 77: #line 352 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 78: #line 354 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, yyvsp[-1].ival, yyvsp[0].exp, EM_lineNum ); ;} break; case 79: #line 358 "chuck.y" { yyval.array_sub = new_array_sub( yyvsp[-1].exp, EM_lineNum ); ;} break; case 80: #line 360 "chuck.y" { yyval.array_sub = prepend_array_sub( yyvsp[0].array_sub, yyvsp[-2].exp, EM_lineNum ); ;} break; case 81: #line 364 "chuck.y" { yyval.array_sub = new_array_sub( NULL, EM_lineNum ); ;} break; case 82: #line 365 "chuck.y" { yyval.array_sub = prepend_array_sub( yyvsp[-2].array_sub, NULL, EM_lineNum ); ;} break; case 83: #line 369 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 84: #line 370 "chuck.y" { yyval.exp = new_exp_decl( yyvsp[-1].type_decl, yyvsp[0].var_decl_list, 0, EM_lineNum ); ;} break; case 85: #line 371 "chuck.y" { yyval.exp = new_exp_decl( yyvsp[-1].type_decl, yyvsp[0].var_decl_list, 1, EM_lineNum ); ;} break; case 86: #line 372 "chuck.y" { yyval.exp = new_exp_decl( NULL, yyvsp[0].var_decl_list, 0, EM_lineNum ); ;} break; case 87: #line 373 "chuck.y" { yyval.exp = new_exp_decl( NULL, yyvsp[0].var_decl_list, 1, EM_lineNum ); ;} break; case 88: #line 377 "chuck.y" { yyval.var_decl_list = new_var_decl_list( yyvsp[0].var_decl, EM_lineNum ); ;} break; case 89: #line 378 "chuck.y" { yyval.var_decl_list = prepend_var_decl_list( yyvsp[-2].var_decl, yyvsp[0].var_decl_list, EM_lineNum ); ;} break; case 90: #line 382 "chuck.y" { yyval.var_decl = new_var_decl( yyvsp[0].sval, NULL, EM_lineNum ); ;} break; case 91: #line 383 "chuck.y" { yyval.var_decl = new_var_decl( yyvsp[-1].sval, yyvsp[0].array_sub, EM_lineNum ); ;} break; case 92: #line 384 "chuck.y" { yyval.var_decl = new_var_decl( yyvsp[-1].sval, yyvsp[0].array_sub, EM_lineNum ); ;} break; case 93: #line 388 "chuck.y" { yyval.ival = ae_op_chuck; ;} break; case 94: #line 389 "chuck.y" { yyval.ival = ae_op_at_chuck; ;} break; case 95: #line 390 "chuck.y" { yyval.ival = ae_op_plus_chuck; ;} break; case 96: #line 391 "chuck.y" { yyval.ival = ae_op_minus_chuck; ;} break; case 97: #line 392 "chuck.y" { yyval.ival = ae_op_times_chuck; ;} break; case 98: #line 393 "chuck.y" { yyval.ival = ae_op_divide_chuck; ;} break; case 99: #line 394 "chuck.y" { yyval.ival = ae_op_shift_right_chuck; ;} break; case 100: #line 395 "chuck.y" { yyval.ival = ae_op_shift_left_chuck; ;} break; case 101: #line 396 "chuck.y" { yyval.ival = ae_op_percent_chuck; ;} break; case 102: #line 397 "chuck.y" { yyval.ival = ae_op_unchuck; ;} break; case 103: #line 398 "chuck.y" { yyval.ival = ae_op_s_and_chuck; ;} break; case 104: #line 399 "chuck.y" { yyval.ival = ae_op_s_or_chuck; ;} break; case 105: #line 400 "chuck.y" { yyval.ival = ae_op_s_xor_chuck; ;} break; case 106: #line 404 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 107: #line 406 "chuck.y" { yyval.exp = new_exp_from_if( yyvsp[-4].exp, yyvsp[-2].exp, yyvsp[0].exp, EM_lineNum ); ;} break; case 108: #line 410 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 109: #line 412 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_or, yyvsp[0].exp, EM_lineNum ); ;} break; case 110: #line 416 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 111: #line 418 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_and, yyvsp[0].exp, EM_lineNum ); ;} break; case 112: #line 422 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 113: #line 424 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_s_or, yyvsp[0].exp, EM_lineNum ); ;} break; case 114: #line 428 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 115: #line 430 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_s_xor, yyvsp[0].exp, EM_lineNum ); ;} break; case 116: #line 434 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 117: #line 436 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_s_and, yyvsp[0].exp, EM_lineNum ); ;} break; case 118: #line 440 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 119: #line 442 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_eq, yyvsp[0].exp, EM_lineNum ); ;} break; case 120: #line 444 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_neq, yyvsp[0].exp, EM_lineNum ); ;} break; case 121: #line 448 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 122: #line 450 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_lt, yyvsp[0].exp, EM_lineNum ); ;} break; case 123: #line 452 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_gt, yyvsp[0].exp, EM_lineNum ); ;} break; case 124: #line 454 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_le, yyvsp[0].exp, EM_lineNum ); ;} break; case 125: #line 456 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_ge, yyvsp[0].exp, EM_lineNum ); ;} break; case 126: #line 460 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 127: #line 462 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_shift_left, yyvsp[0].exp, EM_lineNum ); ;} break; case 128: #line 464 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_shift_right, yyvsp[0].exp, EM_lineNum ); ;} break; case 129: #line 468 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 130: #line 470 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_plus, yyvsp[0].exp, EM_lineNum ); ;} break; case 131: #line 472 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_minus, yyvsp[0].exp, EM_lineNum ); ;} break; case 132: #line 476 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 133: #line 478 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_times, yyvsp[0].exp, EM_lineNum ); ;} break; case 134: #line 480 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_divide, yyvsp[0].exp, EM_lineNum ); ;} break; case 135: #line 482 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_percent, yyvsp[0].exp, EM_lineNum ); ;} break; case 136: #line 486 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 137: #line 488 "chuck.y" { yyval.exp = new_exp_from_binary( yyvsp[-2].exp, ae_op_tilda, yyvsp[0].exp, EM_lineNum ); ;} break; case 138: #line 492 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 139: #line 494 "chuck.y" { yyval.exp = new_exp_from_cast( yyvsp[0].type_decl, yyvsp[-2].exp, EM_lineNum ); ;} break; case 140: #line 498 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 141: #line 500 "chuck.y" { yyval.exp = new_exp_from_unary( ae_op_plusplus, yyvsp[0].exp, EM_lineNum ); ;} break; case 142: #line 502 "chuck.y" { yyval.exp = new_exp_from_unary( ae_op_minusminus, yyvsp[0].exp, EM_lineNum ); ;} break; case 143: #line 504 "chuck.y" { yyval.exp = new_exp_from_unary( yyvsp[-1].ival, yyvsp[0].exp, EM_lineNum ); ;} break; case 144: #line 506 "chuck.y" { yyval.exp = new_exp_from_unary( ae_op_typeof, yyvsp[0].exp, EM_lineNum ); ;} break; case 145: #line 508 "chuck.y" { yyval.exp = new_exp_from_unary( ae_op_sizeof, yyvsp[0].exp, EM_lineNum ); ;} break; case 146: #line 510 "chuck.y" { yyval.exp = new_exp_from_unary2( ae_op_new, yyvsp[0].type_decl, NULL, EM_lineNum ); ;} break; case 147: #line 512 "chuck.y" { yyval.exp = new_exp_from_unary2( ae_op_new, yyvsp[-1].type_decl, yyvsp[0].array_sub, EM_lineNum ); ;} break; case 148: #line 514 "chuck.y" { yyval.exp = new_exp_from_unary3( ae_op_spork, yyvsp[0].stmt, EM_lineNum ); ;} break; case 149: #line 518 "chuck.y" { yyval.ival = ae_op_plus; ;} break; case 150: #line 519 "chuck.y" { yyval.ival = ae_op_minus; ;} break; case 151: #line 520 "chuck.y" { yyval.ival = ae_op_tilda; ;} break; case 152: #line 521 "chuck.y" { yyval.ival = ae_op_exclamation; ;} break; case 153: #line 522 "chuck.y" { yyval.ival = ae_op_times; ;} break; case 154: #line 523 "chuck.y" { yyval.ival = ae_op_spork; ;} break; case 156: #line 530 "chuck.y" { yyval.exp = new_exp_from_dur( yyvsp[-2].exp, yyvsp[0].exp, EM_lineNum ); ;} break; case 157: #line 534 "chuck.y" { yyval.exp = yyvsp[0].exp; ;} break; case 158: #line 536 "chuck.y" { yyval.exp = new_exp_from_array( yyvsp[-1].exp, yyvsp[0].array_sub, EM_lineNum ); ;} break; case 159: #line 538 "chuck.y" { yyval.exp = new_exp_from_func_call( yyvsp[-2].exp, NULL, EM_lineNum ); ;} break; case 160: #line 540 "chuck.y" { yyval.exp = new_exp_from_func_call( yyvsp[-3].exp, yyvsp[-1].exp, EM_lineNum ); ;} break; case 161: #line 542 "chuck.y" { yyval.exp = new_exp_from_member_dot( yyvsp[-2].exp, yyvsp[0].sval, EM_lineNum ); ;} break; case 162: #line 544 "chuck.y" { yyval.exp = new_exp_from_postfix( yyvsp[-1].exp, ae_op_plusplus, EM_lineNum ); ;} break; case 163: #line 546 "chuck.y" { yyval.exp = new_exp_from_postfix( yyvsp[-1].exp, ae_op_minusminus, EM_lineNum ); ;} break; case 164: #line 550 "chuck.y" { yyval.exp = new_exp_from_id( yyvsp[0].sval, EM_lineNum ); ;} break; case 165: #line 551 "chuck.y" { yyval.exp = new_exp_from_int( yyvsp[0].ival, EM_lineNum ); ;} break; case 166: #line 552 "chuck.y" { yyval.exp = new_exp_from_float( yyvsp[0].fval, EM_lineNum ); ;} break; case 167: #line 553 "chuck.y" { yyval.exp = new_exp_from_str( yyvsp[0].sval, EM_lineNum ); ;} break; case 168: #line 554 "chuck.y" { yyval.exp = new_exp_from_array_lit( yyvsp[0].array_sub, EM_lineNum ); ;} break; case 169: #line 555 "chuck.y" { yyval.exp = new_exp_from_hack( yyvsp[-1].exp, EM_lineNum ); ;} break; case 170: #line 556 "chuck.y" { yyval.exp = yyvsp[-1].exp; ;} break; case 171: #line 557 "chuck.y" { yyval.exp = new_exp_from_nil( EM_lineNum ); ;} break; } /* Line 999 of yacc.c. */ #line 2570 "chuck.tab.c" yyvsp -= yylen; yyssp -= yylen; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if YYERROR_VERBOSE yyn = yypact[yystate]; if (YYPACT_NINF < yyn && yyn < YYLAST) { YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); const char* yyprefix; char *yymsg; int yyx; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 0; yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); yycount += 1; if (yycount == 5) { yysize = 0; break; } } yysize += (sizeof ("syntax error, unexpected ") + yystrlen (yytname[yytype])); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); yyp = yystpcpy (yyp, yytname[yytype]); if (yycount < 5) { yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { yyp = yystpcpy (yyp, yyprefix); yyp = yystpcpy (yyp, yytname[yyx]); yyprefix = " or "; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else yyerror ("syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ yyerror ("syntax error"); } if (yyerrstatus == 3) { /* If just tried and failed to reuse lookahead token after an error, discard it. */ /* Return failure if at end of input. */ if (yychar == YYEOF) { /* Pop the error token. */ YYPOPSTACK; /* Pop the rest of the stack. */ while (yyss < yyssp) { YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[*yyssp], yyvsp); YYPOPSTACK; } YYABORT; } YYDSYMPRINTF ("Error: discarding", yytoken, &yylval, &yylloc); yydestruct (yytoken, &yylval); yychar = YYEMPTY; } /* Else will try to reuse lookahead token after shifting the error token. */ goto yyerrlab1; /*----------------------------------------------------. | yyerrlab1 -- error raised explicitly by an action. | `----------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; YYDSYMPRINTF ("Error: popping", yystos[*yyssp], yyvsp, yylsp); yydestruct (yystos[yystate], yyvsp); yyvsp--; yystate = *--yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; YYDPRINTF ((stderr, "Shifting error token, ")); *++yyvsp = yylval; yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*----------------------------------------------. | yyoverflowlab -- parser overflow comes here. | `----------------------------------------------*/ yyoverflowlab: yyerror ("parser stack overflow"); yyresult = 2; /* Fall through. */ #endif yyreturn: #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } #line 2 "chuck.yy.c" /* A lexical scanner generated by flex */ /* Scanner skeleton version: * $Header: /cvs/chuck/src/chuck_win32.c,v 1.87 2007/03/22 06:17:42 gw-chuck_int Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include #ifndef _WIN32 #include #endif /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 94 #define YY_END_OF_BUFFER 95 static yyconst short int yy_accept[218] = { 0, 0, 0, 95, 93, 4, 6, 93, 3, 42, 93, 17, 18, 16, 28, 34, 35, 14, 12, 9, 13, 11, 15, 89, 89, 10, 40, 22, 33, 23, 41, 85, 91, 36, 37, 30, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 38, 29, 39, 43, 5, 21, 0, 92, 0, 0, 26, 0, 0, 7, 0, 8, 0, 90, 2, 1, 0, 90, 89, 0, 89, 0, 19, 32, 24, 72, 20, 71, 25, 31, 0, 86, 91, 0, 91, 91, 91, 52, 91, 91, 91, 91, 50, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 0, 27, 73, 84, 79, 77, 75, 76, 78, 90, 88, 87, 53, 0, 0, 54, 74, 81, 91, 91, 91, 91, 91, 44, 57, 91, 91, 58, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 80, 88, 87, 83, 82, 91, 91, 91, 91, 51, 91, 91, 91, 91, 91, 91, 91, 67, 91, 91, 91, 91, 91, 91, 91, 49, 59, 68, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 69, 91, 91, 46, 45, 91, 91, 91, 91, 91, 91, 91, 63, 47, 55, 66, 70, 91, 61, 91, 91, 91, 65, 91, 48, 56, 91, 91, 91, 91, 60, 64, 62, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 6, 7, 8, 9, 10, 11, 1, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 21, 21, 21, 21, 21, 22, 22, 23, 24, 25, 26, 27, 28, 29, 30, 30, 31, 30, 30, 30, 32, 32, 32, 32, 32, 33, 32, 32, 32, 32, 32, 32, 32, 32, 34, 32, 32, 35, 32, 32, 36, 37, 38, 39, 32, 1, 40, 41, 42, 43, 44, 45, 32, 46, 47, 32, 48, 49, 50, 51, 52, 53, 32, 54, 55, 56, 57, 58, 59, 60, 61, 32, 62, 63, 64, 65, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[66] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1 } ; static yyconst short int yy_base[221] = { 0, 0, 0, 290, 291, 291, 291, 286, 291, 262, 59, 291, 291, 261, 56, 291, 291, 260, 53, 291, 52, 50, 61, 79, 70, 262, 291, 48, 58, 50, 291, 60, 0, 291, 291, 258, 229, 46, 230, 45, 50, 66, 237, 52, 236, 62, 218, 227, 231, 291, 67, 291, 291, 291, 249, 101, 291, 272, 247, 291, 246, 245, 291, 244, 291, 243, 102, 291, 291, 242, 111, 122, 105, 101, 0, 291, 120, 291, 291, 291, 291, 291, 121, 241, 291, 0, 240, 222, 225, 213, 0, 208, 206, 207, 209, 0, 206, 202, 198, 102, 110, 104, 204, 215, 201, 197, 205, 224, 291, 291, 291, 291, 291, 291, 291, 291, 141, 132, 134, 291, 223, 222, 291, 291, 291, 208, 192, 114, 202, 201, 0, 202, 194, 198, 0, 183, 184, 190, 194, 193, 179, 181, 178, 189, 185, 182, 291, 139, 141, 291, 291, 182, 174, 172, 180, 0, 175, 169, 180, 169, 182, 177, 173, 0, 179, 164, 169, 169, 163, 165, 169, 0, 0, 0, 161, 168, 163, 159, 163, 151, 164, 163, 148, 146, 0, 153, 149, 0, 0, 136, 137, 135, 142, 145, 140, 126, 0, 0, 0, 0, 0, 136, 0, 127, 126, 134, 0, 115, 0, 0, 85, 93, 86, 65, 0, 0, 0, 291, 198, 200, 79 } ; static yyconst short int yy_def[221] = { 0, 217, 1, 217, 217, 217, 217, 217, 217, 217, 218, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 219, 217, 217, 217, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 217, 217, 217, 217, 217, 217, 218, 217, 218, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 220, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 219, 217, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 220, 217, 217, 217, 217, 217, 217, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 217, 217, 217, 217, 217, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 219, 0, 217, 217, 217 } ; static yyconst short int yy_nxt[357] = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 24, 25, 26, 27, 28, 29, 30, 31, 32, 32, 32, 32, 32, 32, 33, 4, 34, 35, 32, 36, 37, 38, 39, 40, 32, 41, 32, 32, 32, 42, 32, 43, 44, 45, 46, 47, 32, 48, 32, 32, 49, 50, 51, 52, 56, 59, 62, 64, 66, 66, 66, 76, 77, 67, 81, 82, 65, 63, 68, 118, 60, 78, 79, 80, 83, 69, 70, 84, 71, 71, 71, 107, 91, 88, 57, 70, 89, 71, 71, 71, 93, 73, 73, 92, 99, 94, 56, 100, 72, 95, 73, 73, 74, 102, 96, 97, 103, 73, 216, 72, 66, 66, 66, 117, 117, 73, 73, 215, 108, 116, 116, 116, 73, 73, 73, 214, 57, 74, 70, 213, 71, 71, 71, 119, 120, 121, 122, 135, 73, 137, 117, 117, 136, 73, 73, 139, 73, 212, 140, 116, 116, 116, 138, 147, 147, 148, 148, 153, 154, 73, 147, 147, 148, 148, 211, 210, 209, 73, 208, 147, 207, 148, 206, 205, 204, 203, 147, 147, 148, 148, 202, 201, 200, 199, 147, 198, 148, 55, 55, 55, 85, 85, 197, 196, 195, 194, 193, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180, 179, 178, 177, 176, 175, 174, 173, 172, 171, 170, 169, 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, 158, 157, 156, 155, 152, 151, 150, 149, 146, 145, 144, 143, 142, 141, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 115, 114, 113, 112, 111, 110, 217, 109, 106, 105, 104, 101, 98, 90, 87, 86, 75, 61, 58, 54, 53, 217, 3, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217 } ; static yyconst short int yy_chk[357] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 14, 18, 20, 21, 21, 21, 27, 27, 22, 29, 29, 20, 18, 22, 220, 14, 28, 28, 28, 31, 22, 24, 31, 24, 24, 24, 50, 39, 37, 10, 23, 37, 23, 23, 23, 40, 24, 24, 39, 43, 40, 55, 43, 23, 41, 23, 23, 23, 45, 41, 41, 45, 24, 213, 23, 66, 66, 66, 72, 72, 24, 23, 212, 50, 70, 70, 70, 73, 73, 23, 211, 55, 23, 71, 210, 71, 71, 71, 76, 76, 82, 82, 99, 73, 100, 117, 117, 99, 71, 71, 101, 73, 207, 101, 116, 116, 116, 100, 117, 117, 118, 118, 127, 127, 71, 147, 147, 148, 148, 205, 204, 203, 71, 201, 117, 195, 118, 194, 193, 192, 191, 147, 117, 148, 118, 190, 189, 186, 185, 147, 183, 148, 218, 218, 218, 219, 219, 182, 181, 180, 179, 178, 177, 176, 175, 174, 170, 169, 168, 167, 166, 165, 164, 162, 161, 160, 159, 158, 157, 156, 154, 153, 152, 151, 145, 144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 133, 132, 131, 129, 128, 126, 125, 121, 120, 107, 106, 105, 104, 103, 102, 98, 97, 96, 94, 93, 92, 91, 89, 88, 87, 86, 83, 69, 65, 63, 61, 60, 58, 57, 54, 48, 47, 46, 44, 42, 38, 36, 35, 25, 17, 13, 9, 7, 3, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "chuck.lex" #define INITIAL 0 #line 11 "chuck.lex" /*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: chuck.yy.c // desc: chuck lexer // // author: Ge Wang (gewang.cs.princeton.edu) - generated by lex // Perry R. Cook (prc@cs.princeton.edu) // // based on the ansi C grammar by Jeff Lee, maintained by Jutta Degener // // date: Summer 2002 //----------------------------------------------------------------------------- #include #include #include "chuck_utils.h" #include "chuck_absyn.h" #include "chuck_errmsg.h" #ifndef __PLATFORM_WIN32__ #include "chuck.tab.h" #else #include "chuck_win32.h" #endif // globals extern YYSTYPE yylval; int char_pos = 1; // define error handling #define YY_FATAL_ERROR(msg) EM_error2( 0, msg ) #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif int yywrap(void); void adjust(); c_str strip_lit( c_str str ); c_str alloc_str( c_str str ); long htol( c_str str ); int comment(); int block_comment(); #if defined(_cplusplus) || defined(__cplusplus) } #endif // yywrap() int yywrap( void ) { char_pos = 1; return 1; } // adjust() void adjust() { EM_tokPos = char_pos; char_pos += yyleng; } // strip c_str strip_lit( c_str str ) { str[strlen(str)-1] = '\0'; return str+1; } // alloc_str() c_str alloc_str( c_str str ) { c_str s = (c_str)malloc( strlen(str) + 1 ); strcpy( s, str ); return s; } // to long long htol( c_str str ) { char * c = str; unsigned long n = 0; // skip over 0x c += 2; while( *c ) { n <<= 4; switch( *c ) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': n += *c - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': n += *c - 'a' + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': n += *c - 'A' + 10; break; } c++; } return n; } // block comment hack (thanks to unput/yytext_ptr inconsistency) #define block_comment_hack loop: \ while ((c = input()) != '*' && c != 0 && c != EOF ) \ if( c == '\n' ) EM_newline(); \ if( c == EOF ) adjust(); \ else if( (c1 = input()) != '/' && c != 0 ) \ { \ unput(c1); \ goto loop; \ } \ if( c != 0 ) adjust(); // comment hack #define comment_hack \ while ((c = input()) != '\n' && c != '\r' && c != 0 && c != EOF ); \ if (c != 0) { \ adjust(); \ if (c == '\n') EM_newline(); \ } #line 674 "chuck.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else \ { \ errno=0; \ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ { \ if( errno != EINTR) \ { \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ break; \ } \ errno=0; \ clearerr(yyin); \ } \ } #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; #line 168 "chuck.lex" #line 839 "chuck.yy.c" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 218 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_base[yy_current_state] != 291 ); yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP #line 170 "chuck.lex" { char c; adjust(); comment_hack; continue; } YY_BREAK case 2: YY_RULE_SETUP #line 171 "chuck.lex" { char c, c1; adjust(); block_comment_hack; continue; } YY_BREAK case 3: YY_RULE_SETUP #line 172 "chuck.lex" { adjust(); continue; } YY_BREAK case 4: YY_RULE_SETUP #line 173 "chuck.lex" { adjust(); continue; } YY_BREAK case 5: YY_RULE_SETUP #line 174 "chuck.lex" { adjust(); EM_newline(); continue; } YY_BREAK case 6: YY_RULE_SETUP #line 175 "chuck.lex" { adjust(); EM_newline(); continue; } YY_BREAK case 7: YY_RULE_SETUP #line 177 "chuck.lex" { adjust(); return PLUSPLUS; } YY_BREAK case 8: YY_RULE_SETUP #line 178 "chuck.lex" { adjust(); return MINUSMINUS; } YY_BREAK case 9: YY_RULE_SETUP #line 180 "chuck.lex" { adjust(); return COMMA; } YY_BREAK case 10: YY_RULE_SETUP #line 181 "chuck.lex" { adjust(); return COLON; } YY_BREAK case 11: YY_RULE_SETUP #line 182 "chuck.lex" { adjust(); return DOT; } YY_BREAK case 12: YY_RULE_SETUP #line 183 "chuck.lex" { adjust(); return PLUS; } YY_BREAK case 13: YY_RULE_SETUP #line 184 "chuck.lex" { adjust(); return MINUS; } YY_BREAK case 14: YY_RULE_SETUP #line 185 "chuck.lex" { adjust(); return TIMES; } YY_BREAK case 15: YY_RULE_SETUP #line 186 "chuck.lex" { adjust(); return DIVIDE; } YY_BREAK case 16: YY_RULE_SETUP #line 187 "chuck.lex" { adjust(); return PERCENT; } YY_BREAK case 17: YY_RULE_SETUP #line 188 "chuck.lex" { adjust(); return POUND; } YY_BREAK case 18: YY_RULE_SETUP #line 189 "chuck.lex" { adjust(); return DOLLAR; } YY_BREAK case 19: YY_RULE_SETUP #line 191 "chuck.lex" { adjust(); return COLONCOLON; } YY_BREAK case 20: YY_RULE_SETUP #line 192 "chuck.lex" { adjust(); return EQ; } YY_BREAK case 21: YY_RULE_SETUP #line 193 "chuck.lex" { adjust(); return NEQ; } YY_BREAK case 22: YY_RULE_SETUP #line 194 "chuck.lex" { adjust(); return LT; } YY_BREAK case 23: YY_RULE_SETUP #line 195 "chuck.lex" { adjust(); return GT; } YY_BREAK case 24: YY_RULE_SETUP #line 196 "chuck.lex" { adjust(); return LE; } YY_BREAK case 25: YY_RULE_SETUP #line 197 "chuck.lex" { adjust(); return GE; } YY_BREAK case 26: YY_RULE_SETUP #line 198 "chuck.lex" { adjust(); return AND; } YY_BREAK case 27: YY_RULE_SETUP #line 199 "chuck.lex" { adjust(); return OR; } YY_BREAK case 28: YY_RULE_SETUP #line 200 "chuck.lex" { adjust(); return S_AND; } YY_BREAK case 29: YY_RULE_SETUP #line 201 "chuck.lex" { adjust(); return S_OR; } YY_BREAK case 30: YY_RULE_SETUP #line 202 "chuck.lex" { adjust(); return S_XOR; } YY_BREAK case 31: YY_RULE_SETUP #line 203 "chuck.lex" { adjust(); return SHIFT_RIGHT; } YY_BREAK case 32: YY_RULE_SETUP #line 204 "chuck.lex" { adjust(); return SHIFT_LEFT; } YY_BREAK case 33: YY_RULE_SETUP #line 205 "chuck.lex" { adjust(); return ASSIGN; } YY_BREAK case 34: YY_RULE_SETUP #line 206 "chuck.lex" { adjust(); return LPAREN; } YY_BREAK case 35: YY_RULE_SETUP #line 207 "chuck.lex" { adjust(); return RPAREN; } YY_BREAK case 36: YY_RULE_SETUP #line 208 "chuck.lex" { adjust(); return LBRACK; } YY_BREAK case 37: YY_RULE_SETUP #line 209 "chuck.lex" { adjust(); return RBRACK; } YY_BREAK case 38: YY_RULE_SETUP #line 210 "chuck.lex" { adjust(); return LBRACE; } YY_BREAK case 39: YY_RULE_SETUP #line 211 "chuck.lex" { adjust(); return RBRACE; } YY_BREAK case 40: YY_RULE_SETUP #line 212 "chuck.lex" { adjust(); return SEMICOLON; } YY_BREAK case 41: YY_RULE_SETUP #line 213 "chuck.lex" { adjust(); return QUESTION; } YY_BREAK case 42: YY_RULE_SETUP #line 214 "chuck.lex" { adjust(); return EXCLAMATION; } YY_BREAK case 43: YY_RULE_SETUP #line 215 "chuck.lex" { adjust(); return TILDA; } YY_BREAK case 44: YY_RULE_SETUP #line 216 "chuck.lex" { adjust(); return FOR; } YY_BREAK case 45: YY_RULE_SETUP #line 217 "chuck.lex" { adjust(); return WHILE; } YY_BREAK case 46: YY_RULE_SETUP #line 218 "chuck.lex" { adjust(); return UNTIL; } YY_BREAK case 47: YY_RULE_SETUP #line 219 "chuck.lex" { adjust(); return LOOP; } YY_BREAK case 48: YY_RULE_SETUP #line 220 "chuck.lex" { adjust(); return CONTINUE; } YY_BREAK case 49: YY_RULE_SETUP #line 221 "chuck.lex" { adjust(); return BREAK; } YY_BREAK case 50: YY_RULE_SETUP #line 222 "chuck.lex" { adjust(); return IF; } YY_BREAK case 51: YY_RULE_SETUP #line 223 "chuck.lex" { adjust(); return ELSE; } YY_BREAK case 52: YY_RULE_SETUP #line 224 "chuck.lex" { adjust(); return DO; } YY_BREAK case 53: YY_RULE_SETUP #line 225 "chuck.lex" { adjust(); return L_HACK; } YY_BREAK case 54: YY_RULE_SETUP #line 226 "chuck.lex" { adjust(); return R_HACK; } YY_BREAK case 55: YY_RULE_SETUP #line 228 "chuck.lex" { adjust(); return RETURN; } YY_BREAK case 56: YY_RULE_SETUP #line 230 "chuck.lex" { adjust(); return FUNCTION; } YY_BREAK case 57: YY_RULE_SETUP #line 231 "chuck.lex" { adjust(); return FUNCTION; } YY_BREAK case 58: YY_RULE_SETUP #line 232 "chuck.lex" { adjust(); return NEW; } YY_BREAK case 59: YY_RULE_SETUP #line 233 "chuck.lex" { adjust(); return CLASS; } YY_BREAK case 60: YY_RULE_SETUP #line 234 "chuck.lex" { adjust(); return INTERFACE; } YY_BREAK case 61: YY_RULE_SETUP #line 235 "chuck.lex" { adjust(); return EXTENDS; } YY_BREAK case 62: YY_RULE_SETUP #line 236 "chuck.lex" { adjust(); return IMPLEMENTS; } YY_BREAK case 63: YY_RULE_SETUP #line 237 "chuck.lex" { adjust(); return PUBLIC; } YY_BREAK case 64: YY_RULE_SETUP #line 238 "chuck.lex" { adjust(); return PROTECTED; } YY_BREAK case 65: YY_RULE_SETUP #line 239 "chuck.lex" { adjust(); return PRIVATE; } YY_BREAK case 66: YY_RULE_SETUP #line 240 "chuck.lex" { adjust(); return STATIC; } YY_BREAK case 67: YY_RULE_SETUP #line 241 "chuck.lex" { adjust(); return ABSTRACT; } YY_BREAK case 68: YY_RULE_SETUP #line 242 "chuck.lex" { adjust(); return CONST; } YY_BREAK case 69: YY_RULE_SETUP #line 243 "chuck.lex" { adjust(); return SPORK; } YY_BREAK case 70: YY_RULE_SETUP #line 244 "chuck.lex" { adjust(); return TYPEOF; } YY_BREAK case 71: YY_RULE_SETUP #line 246 "chuck.lex" { adjust(); return CHUCK; } YY_BREAK case 72: YY_RULE_SETUP #line 247 "chuck.lex" { adjust(); return UNCHUCK; } YY_BREAK case 73: YY_RULE_SETUP #line 248 "chuck.lex" { adjust(); return UNCHUCK; } YY_BREAK case 74: YY_RULE_SETUP #line 249 "chuck.lex" { adjust(); return AT_CHUCK; } YY_BREAK case 75: YY_RULE_SETUP #line 250 "chuck.lex" { adjust(); return PLUS_CHUCK; } YY_BREAK case 76: YY_RULE_SETUP #line 251 "chuck.lex" { adjust(); return MINUS_CHUCK; } YY_BREAK case 77: YY_RULE_SETUP #line 252 "chuck.lex" { adjust(); return TIMES_CHUCK; } YY_BREAK case 78: YY_RULE_SETUP #line 253 "chuck.lex" { adjust(); return DIVIDE_CHUCK; } YY_BREAK case 79: YY_RULE_SETUP #line 254 "chuck.lex" { adjust(); return S_AND_CHUCK; } YY_BREAK case 80: YY_RULE_SETUP #line 255 "chuck.lex" { adjust(); return S_OR_CHUCK; } YY_BREAK case 81: YY_RULE_SETUP #line 256 "chuck.lex" { adjust(); return S_XOR_CHUCK; } YY_BREAK case 82: YY_RULE_SETUP #line 257 "chuck.lex" { adjust(); return SHIFT_RIGHT_CHUCK; } YY_BREAK case 83: YY_RULE_SETUP #line 258 "chuck.lex" { adjust(); return SHIFT_LEFT_CHUCK; } YY_BREAK case 84: YY_RULE_SETUP #line 259 "chuck.lex" { adjust(); return PERCENT_CHUCK; } YY_BREAK case 85: YY_RULE_SETUP #line 260 "chuck.lex" { adjust(); return AT_SYM; } YY_BREAK case 86: YY_RULE_SETUP #line 261 "chuck.lex" { adjust(); return ATAT_SYM; } YY_BREAK case 87: YY_RULE_SETUP #line 263 "chuck.lex" { adjust(); yylval.ival=htol(yytext); return NUM; } YY_BREAK case 88: YY_RULE_SETUP #line 264 "chuck.lex" { adjust(); yylval.ival=atoi(yytext); return NUM; } YY_BREAK case 89: YY_RULE_SETUP #line 265 "chuck.lex" { adjust(); yylval.ival=atoi(yytext); return NUM; } YY_BREAK case 90: YY_RULE_SETUP #line 266 "chuck.lex" { adjust(); yylval.fval=atof(yytext); return FLOAT; } YY_BREAK case 91: YY_RULE_SETUP #line 267 "chuck.lex" { adjust(); yylval.sval=alloc_str(yytext); return ID; } YY_BREAK case 92: YY_RULE_SETUP #line 268 "chuck.lex" { adjust(); yylval.sval=alloc_str(strip_lit(yytext)); return STRING_LIT; } YY_BREAK case 93: YY_RULE_SETUP #line 270 "chuck.lex" { adjust(); EM_error( EM_tokPos, "illegal token" ); } YY_BREAK case 94: YY_RULE_SETUP #line 272 "chuck.lex" ECHO; YY_BREAK #line 1392 "chuck.yy.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_c_buf_p; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 218 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 218 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 217); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; return c; } #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifndef _WIN32 #include #else #ifndef YY_ALWAYS_INTERACTIVE #ifndef YY_NEVER_INTERACTIVE extern int isatty YY_PROTO(( int )); #endif #endif #endif #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif #line 272 "chuck.lex" /* // comment int comment() { char c; while ((c = yyinput()) != '\n' && c != '\r' && c != 0 && c != EOF ); if (c != 0) { adjust(); if (c == '\n') EM_newline(); } return 0; } // block comment int block_comment() { char c, c1; loop: while ((c = yyinput()) != '*' && c != 0 && c != EOF ) if( c == '\n' ) EM_newline(); if( c == EOF ) { adjust(); return 1; } if( (c1 = yyinput()) != '/' && c != 0 ) { unput(c1); goto loop; } if( c != 0 ) adjust(); return 0; } */ chuck-1.2.0.8.dfsg/src/chuck_win32.dsp0000644000175000017500000002534210600421721015762 0ustar piempiem# Microsoft Developer Studio Project File - Name="chuck_win32" - Package Owner=<4> # Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 CFG=chuck_win32 - Win32 Debug !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run !MESSAGE !MESSAGE NMAKE /f "chuck_win32.mak". !MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: !MESSAGE !MESSAGE NMAKE /f "chuck_win32.mak" CFG="chuck_win32 - Win32 Debug" !MESSAGE !MESSAGE Possible choices for configuration are: !MESSAGE !MESSAGE "chuck_win32 - Win32 Release" (based on "Win32 (x86) Console Application") !MESSAGE "chuck_win32 - Win32 Debug" (based on "Win32 (x86) Console Application") !MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 # PROP Scc_ProjName "" # PROP Scc_LocalPath "" CPP=cl.exe RSC=rc.exe !IF "$(CFG)" == "chuck_win32 - Win32 Release" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 0 # PROP BASE Output_Dir "Release" # PROP BASE Intermediate_Dir "Release" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 0 # PROP Output_Dir "Release" # PROP Intermediate_Dir "Release" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GR /GX /O2 /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /D "__PLATFORM_WIN32__" /YX /FD /c # ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib dinput.lib dxguid.lib wsock32.lib winmm.lib /nologo /subsystem:console /machine:I386 /out:"Release/chuck.exe" !ELSEIF "$(CFG)" == "chuck_win32 - Win32 Debug" # PROP BASE Use_MFC 0 # PROP BASE Use_Debug_Libraries 1 # PROP BASE Output_Dir "Debug" # PROP BASE Intermediate_Dir "Debug" # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 # PROP Output_Dir "Debug" # PROP Intermediate_Dir "Debug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GR /GX /ZI /Od /D "_DEBUG" /D "__PLATFORM_WIN32__" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D "__WINDOWS_DS__" /YX /FD /GZ /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe # ADD BASE BSC32 /nologo # ADD BSC32 /nologo LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept # ADD LINK32 dinput.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib dsound.lib dxguid.lib wsock32.lib winmm.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/chuck.exe" /pdbtype:sept !ENDIF # Begin Target # Name "chuck_win32 - Win32 Release" # Name "chuck_win32 - Win32 Debug" # Begin Group "Source Files" # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" # Begin Source File SOURCE=.\chuck_absyn.cpp # End Source File # Begin Source File SOURCE=.\chuck_bbq.cpp # End Source File # Begin Source File SOURCE=.\chuck_compile.cpp # End Source File # Begin Source File SOURCE=.\chuck_console.cpp # End Source File # Begin Source File SOURCE=.\chuck_dl.cpp # End Source File # Begin Source File SOURCE=.\chuck_emit.cpp # End Source File # Begin Source File SOURCE=.\chuck_errmsg.cpp # End Source File # Begin Source File SOURCE=.\chuck_frame.cpp # End Source File # Begin Source File SOURCE=.\chuck_globals.cpp # End Source File # Begin Source File SOURCE=.\chuck_instr.cpp # End Source File # Begin Source File SOURCE=.\chuck_lang.cpp # End Source File # Begin Source File SOURCE=.\chuck_main.cpp # End Source File # Begin Source File SOURCE=.\chuck_oo.cpp # End Source File # Begin Source File SOURCE=.\chuck_otf.cpp # End Source File # Begin Source File SOURCE=.\chuck_parse.cpp # End Source File # Begin Source File SOURCE=.\chuck_scan.cpp # End Source File # Begin Source File SOURCE=.\chuck_shell.cpp # End Source File # Begin Source File SOURCE=.\chuck_stats.cpp # End Source File # Begin Source File SOURCE=.\chuck_symbol.cpp # End Source File # Begin Source File SOURCE=.\chuck_table.cpp # End Source File # Begin Source File SOURCE=.\chuck_type.cpp # End Source File # Begin Source File SOURCE=.\chuck_ugen.cpp # End Source File # Begin Source File SOURCE=.\chuck_utils.cpp # End Source File # Begin Source File SOURCE=.\chuck_vm.cpp # End Source File # Begin Source File SOURCE=.\chuck_win32.c # End Source File # Begin Source File SOURCE=.\digiio_rtaudio.cpp # End Source File # Begin Source File SOURCE=.\hidio_sdl.cpp # End Source File # Begin Source File SOURCE=.\midiio_rtmidi.cpp # End Source File # Begin Source File SOURCE=.\rtaudio.cpp # End Source File # Begin Source File SOURCE=.\rtmidi.cpp # End Source File # Begin Source File SOURCE=.\ugen_filter.cpp # End Source File # Begin Source File SOURCE=.\ugen_osc.cpp # End Source File # Begin Source File SOURCE=.\ugen_stk.cpp # End Source File # Begin Source File SOURCE=.\ugen_xxx.cpp # End Source File # Begin Source File SOURCE=.\ulib_machine.cpp # End Source File # Begin Source File SOURCE=.\ulib_math.cpp # End Source File # Begin Source File SOURCE=.\ulib_opsc.cpp # End Source File # Begin Source File SOURCE=.\ulib_std.cpp # End Source File # Begin Source File SOURCE=.\util_buffers.cpp # End Source File # Begin Source File SOURCE=.\util_console.cpp # End Source File # Begin Source File SOURCE=.\util_hid.cpp !IF "$(CFG)" == "chuck_win32 - Win32 Release" !ELSEIF "$(CFG)" == "chuck_win32 - Win32 Debug" # ADD CPP /GX !ENDIF # End Source File # Begin Source File SOURCE=.\util_math.c # End Source File # Begin Source File SOURCE=.\util_network.c # End Source File # Begin Source File SOURCE=.\util_opsc.cpp # End Source File # Begin Source File SOURCE=.\util_raw.c # End Source File # Begin Source File SOURCE=.\util_sndfile.c # End Source File # Begin Source File SOURCE=.\util_string.cpp # End Source File # Begin Source File SOURCE=.\util_thread.cpp # End Source File # Begin Source File SOURCE=.\util_xforms.c # End Source File # End Group # Begin Group "Header Files" # PROP Default_Filter "h;hpp;hxx;hm;inl" # Begin Source File SOURCE=.\chuck_absyn.h # End Source File # Begin Source File SOURCE=.\chuck_bbq.h # End Source File # Begin Source File SOURCE=.\chuck_compile.h # End Source File # Begin Source File SOURCE=.\chuck_console.h # End Source File # Begin Source File SOURCE=.\chuck_def.h # End Source File # Begin Source File SOURCE=.\chuck_dl.h # End Source File # Begin Source File SOURCE=.\chuck_emit.h # End Source File # Begin Source File SOURCE=.\chuck_errmsg.h # End Source File # Begin Source File SOURCE=.\chuck_frame.h # End Source File # Begin Source File SOURCE=.\chuck_globals.h # End Source File # Begin Source File SOURCE=.\chuck_instr.h # End Source File # Begin Source File SOURCE=.\chuck_lang.h # End Source File # Begin Source File SOURCE=.\chuck_oo.h # End Source File # Begin Source File SOURCE=.\chuck_otf.h # End Source File # Begin Source File SOURCE=.\chuck_parse.h # End Source File # Begin Source File SOURCE=.\chuck_scan.h # End Source File # Begin Source File SOURCE=.\chuck_shell.h # End Source File # Begin Source File SOURCE=.\chuck_stats.h # End Source File # Begin Source File SOURCE=.\chuck_symbol.h # End Source File # Begin Source File SOURCE=.\chuck_table.h # End Source File # Begin Source File SOURCE=.\chuck_type.h # End Source File # Begin Source File SOURCE=.\chuck_ugen.h # End Source File # Begin Source File SOURCE=.\chuck_utils.h # End Source File # Begin Source File SOURCE=.\chuck_vm.h # End Source File # Begin Source File SOURCE=.\chuck_win32.h # End Source File # Begin Source File SOURCE=.\digiio_rtaudio.h # End Source File # Begin Source File SOURCE=.\hidio_sdl.h # End Source File # Begin Source File SOURCE=.\midiio_rtmidi.h # End Source File # Begin Source File SOURCE=.\rtaudio.h # End Source File # Begin Source File SOURCE=.\rterror.h # End Source File # Begin Source File SOURCE=.\rtmidi.h # End Source File # Begin Source File SOURCE=.\ugen_filter.h # End Source File # Begin Source File SOURCE=.\ugen_osc.h # End Source File # Begin Source File SOURCE=.\ugen_stk.h # End Source File # Begin Source File SOURCE=.\ugen_xxx.h # End Source File # Begin Source File SOURCE=.\ulib_machine.h # End Source File # Begin Source File SOURCE=.\ulib_math.h # End Source File # Begin Source File SOURCE=.\ulib_opsc.h # End Source File # Begin Source File SOURCE=.\ulib_std.h # End Source File # Begin Source File SOURCE=.\util_buffers.h # End Source File # Begin Source File SOURCE=.\util_console.h # End Source File # Begin Source File SOURCE=.\util_hid.h # End Source File # Begin Source File SOURCE=.\util_math.h # End Source File # Begin Source File SOURCE=.\util_network.h # End Source File # Begin Source File SOURCE=.\util_opsc.h # End Source File # Begin Source File SOURCE=.\util_raw.h # End Source File # Begin Source File SOURCE=.\util_sndfile.h # End Source File # Begin Source File SOURCE=.\util_string.h # End Source File # Begin Source File SOURCE=.\util_thread.h # End Source File # Begin Source File SOURCE=.\util_xforms.h # End Source File # End Group # Begin Group "Resource Files" # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" # End Group # End Target # End Project chuck-1.2.0.8.dfsg/src/chuck_win32.dsw0000644000175000017500000000104110600421721015757 0ustar piempiemMicrosoft Developer Studio Workspace File, Format Version 6.00 # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! ############################################################################### Project: "chuck_win32"=.\chuck_win32.dsp - Package Owner=<4> Package=<5> {{{ }}} Package=<4> {{{ }}} ############################################################################### Global: Package=<5> {{{ }}} Package=<3> {{{ }}} ############################################################################### chuck-1.2.0.8.dfsg/src/chuck_win32.h0000644000175000017500000001353510600421721015424 0ustar piempiem/* A Bison parser, made by GNU Bison 1.875b. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 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, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { ID = 258, STRING_LIT = 259, NUM = 260, FLOAT = 261, POUND = 262, COMMA = 263, COLON = 264, SEMICOLON = 265, LPAREN = 266, RPAREN = 267, LBRACK = 268, RBRACK = 269, LBRACE = 270, RBRACE = 271, DOT = 272, PLUS = 273, MINUS = 274, TIMES = 275, DIVIDE = 276, PERCENT = 277, EQ = 278, NEQ = 279, LT = 280, LE = 281, GT = 282, GE = 283, AND = 284, OR = 285, ASSIGN = 286, IF = 287, THEN = 288, ELSE = 289, WHILE = 290, FOR = 291, DO = 292, LOOP = 293, BREAK = 294, CONTINUE = 295, NULL_TOK = 296, FUNCTION = 297, RETURN = 298, QUESTION = 299, EXCLAMATION = 300, S_OR = 301, S_AND = 302, S_XOR = 303, PLUSPLUS = 304, MINUSMINUS = 305, DOLLAR = 306, SIMULT = 307, PATTERN = 308, CODE = 309, TRANSPORT = 310, HOST = 311, TIME = 312, WHENEVER = 313, NEXT = 314, UNTIL = 315, EVERY = 316, BEFORE = 317, AFTER = 318, AT = 319, AT_SYM = 320, ATAT_SYM = 321, NEW = 322, SIZEOF = 323, TYPEOF = 324, SAME = 325, PLUS_CHUCK = 326, MINUS_CHUCK = 327, TIMES_CHUCK = 328, DIVIDE_CHUCK = 329, S_AND_CHUCK = 330, S_OR_CHUCK = 331, S_XOR_CHUCK = 332, SHIFT_RIGHT_CHUCK = 333, SHIFT_LEFT_CHUCK = 334, PERCENT_CHUCK = 335, SHIFT_RIGHT = 336, SHIFT_LEFT = 337, TILDA = 338, CHUCK = 339, COLONCOLON = 340, S_CHUCK = 341, AT_CHUCK = 342, LEFT_S_CHUCK = 343, UNCHUCK = 344, CLASS = 345, INTERFACE = 346, EXTENDS = 347, IMPLEMENTS = 348, PUBLIC = 349, PROTECTED = 350, PRIVATE = 351, STATIC = 352, ABSTRACT = 353, CONST = 354, SPORK = 355, L_HACK = 356, R_HACK = 357 }; #endif #define ID 258 #define STRING_LIT 259 #define NUM 260 #define FLOAT 261 #define POUND 262 #define COMMA 263 #define COLON 264 #define SEMICOLON 265 #define LPAREN 266 #define RPAREN 267 #define LBRACK 268 #define RBRACK 269 #define LBRACE 270 #define RBRACE 271 #define DOT 272 #define PLUS 273 #define MINUS 274 #define TIMES 275 #define DIVIDE 276 #define PERCENT 277 #define EQ 278 #define NEQ 279 #define LT 280 #define LE 281 #define GT 282 #define GE 283 #define AND 284 #define OR 285 #define ASSIGN 286 #define IF 287 #define THEN 288 #define ELSE 289 #define WHILE 290 #define FOR 291 #define DO 292 #define LOOP 293 #define BREAK 294 #define CONTINUE 295 #define NULL_TOK 296 #define FUNCTION 297 #define RETURN 298 #define QUESTION 299 #define EXCLAMATION 300 #define S_OR 301 #define S_AND 302 #define S_XOR 303 #define PLUSPLUS 304 #define MINUSMINUS 305 #define DOLLAR 306 #define SIMULT 307 #define PATTERN 308 #define CODE 309 #define TRANSPORT 310 #define HOST 311 #define TIME 312 #define WHENEVER 313 #define NEXT 314 #define UNTIL 315 #define EVERY 316 #define BEFORE 317 #define AFTER 318 #define AT 319 #define AT_SYM 320 #define ATAT_SYM 321 #define NEW 322 #define SIZEOF 323 #define TYPEOF 324 #define SAME 325 #define PLUS_CHUCK 326 #define MINUS_CHUCK 327 #define TIMES_CHUCK 328 #define DIVIDE_CHUCK 329 #define S_AND_CHUCK 330 #define S_OR_CHUCK 331 #define S_XOR_CHUCK 332 #define SHIFT_RIGHT_CHUCK 333 #define SHIFT_LEFT_CHUCK 334 #define PERCENT_CHUCK 335 #define SHIFT_RIGHT 336 #define SHIFT_LEFT 337 #define TILDA 338 #define CHUCK 339 #define COLONCOLON 340 #define S_CHUCK 341 #define AT_CHUCK 342 #define LEFT_S_CHUCK 343 #define UNCHUCK 344 #define CLASS 345 #define INTERFACE 346 #define EXTENDS 347 #define IMPLEMENTS 348 #define PUBLIC 349 #define PROTECTED 350 #define PRIVATE 351 #define STATIC 352 #define ABSTRACT 353 #define CONST 354 #define SPORK 355 #define L_HACK 356 #define R_HACK 357 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 59 "chuck.y" typedef union YYSTYPE { int pos; int ival; double fval; c_str sval; a_Program program; a_Section program_section; a_Stmt_List stmt_list; a_Class_Def class_def; a_Class_Ext class_ext; a_Class_Body class_body; a_Stmt stmt; a_Exp exp; a_Func_Def func_def; a_Var_Decl_List var_decl_list; a_Var_Decl var_decl; a_Type_Decl type_decl; a_Arg_List arg_list; a_Id_List id_list; a_Array_Sub array_sub; } YYSTYPE; /* Line 1252 of yacc.c. */ #line 264 "chuck.tab.h" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; chuck-1.2.0.8.dfsg/src/chuck_win32.opt0000644000175000017500000013700010600421721015771 0ustar piempiemࡱ>   I"#$%&'()*,-./012346789:;<=>@ABCDEFGHKLMNOPQRSUVWXYZ[\]Root Entry2dWorkspace State  Browser Editor chuck_win32/D:\gewang\research\chuck_dev\v2\chuck_win32.dspIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHwin32/D:\gewang\research\chuck_dev\v2\chuck_win32.dspIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHMLJLwin32/D:\gewang\research\chuck_dev\v2\chuck_win32.dspIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHWorkspace Window"!IPI_chuck_win32 +IPI_ 5ClassView Window"? chuck_win32 ClassViewchuck_win32 classeschuck_win32 classesFileView%Workspace 'chuck_win32': 1 project(s)%Workspace 'chuck_win32': 1 project(s)chuck_win32 files ClassViewSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dH`CHUCK_WIN32 - WIN32 RELEASEchuck_win32.dspCProjectCHUCK_WIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dH`SEchuck_win32.dspCProjectCHUCK_WIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dH CClsFldSlob chuck_win32k_win32.dspCProjectCHUCK_WIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHDebuggerJDocumentsT Watch1Watch2Watch3Watch4CK_WIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHWatch1Watch2Watch3Watch4CK_WIN32 - WIN32 RELEASEchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR CTargetItemchuck_win32 - Win32 Releasechuck_win32 - Win32 DebugSSBR Source Files CProjGroupSSBRDJW Header Files CProjGroupSSBRDJWResource Files CProjGroupSSBRDJWDJWDJWp d8lۭ@` d8lۭ\P d8lۭx@ d8lۭ0d8lۭ d8lۭd8lۭ% d8lۭd8lۭ0d8lۭLd8lۭhd8lۭxd8lۭhd8lۭXd8lۭHd8lۭ8d8lۭ% (d8lۭ<d8lۭXd8lۭtd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭd8lۭr% d8lۭdxd8lۭhd8lۭSd8lۭSd8lۭTd8lۭUd8lۭ Vd8lۭ(Wd8lۭDXd8lۭM% Yd8lۭZd8lۭp[d8lۭ`\d8lۭP]d8lۭ@^d8lۭ0_d8lۭ4 `d8lۭPPd8xۭl۰d8xۭ(% Hݰd8xۭx߰d8xۭd8xۭd8xۭd8xۭ$8d8xۭ@hd8xۭ\d8xۭxd8xۭpرd8xۭ% 0ڱd8xۭܱd8xۭ߱d8xۭ0d8xۭ0`d8xۭLd8xۭhd8xۭd8xۭ߲d8xۭ(d8xۭ% Xd8xۭd8xۭ d8xۭ<d8xۭXd8xۭtHd8xۭxd8xۭd8xۭd8xۭ@d8xۭ% p`߆pd8xۭ,d8xۭHd8xۭdd8xۭ0d8xۭ`d8xۭ0d8xۭ`d8xۭd8xۭ d8xۭ% d8xۭTp d8xۭp` d8xۭP d8xۭ@ d8xۭ0d8xۭ d8xۭd8xۭd8xۭ4d8xۭo% d8xۭ|d8xۭd8xۭxd8xۭhd8xۭXd8xۭHd8xۭ$8d8xۭ@(d8xۭ\d8xۭJ% xd8xۭd8xۭd8xۭd8xۭd8xۭd8xۭ0d8xۭLd8xۭhd8xۭxd8xۭ%% hd8xۭSd8xۭSd8xۭTd8xۭ Ud8xۭ<Vd8xۭXWd8xۭtXd8xۭYd8`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y`y|#d`߆#dHchuck-1.2.0.8.dfsg/src/digiio_rtaudio.cpp0000644000175000017500000010770610600421721016637 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: digiio_rtaudio.cpp // desc: digitalio over rtaudio (from Gary Scavone) // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) //----------------------------------------------------------------------------- #include "digiio_rtaudio.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "chuck_globals.h" #include "rtaudio.h" #include "rtmidi.h" // #include #if (defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__)) && !defined(__WINDOWS_PTHREAD__) #include #include #else #include #include #endif // extern "C" void signal_int( int ); // static BOOL__ Digitalio::m_init = FALSE; DWORD__ Digitalio::m_start = 0; DWORD__ Digitalio::m_tick_count = 0; DWORD__ Digitalio::m_num_channels_out = NUM_CHANNELS_DEFAULT; DWORD__ Digitalio::m_num_channels_in = NUM_CHANNELS_DEFAULT; DWORD__ Digitalio::m_sampling_rate = SAMPLING_RATE_DEFAULT; DWORD__ Digitalio::m_bps = BITS_PER_SAMPLE_DEFAULT; DWORD__ Digitalio::m_buffer_size = BUFFER_SIZE_DEFAULT; DWORD__ Digitalio::m_num_buffers = NUM_BUFFERS_DEFAULT; RtAudio * Digitalio::m_rtaudio = NULL; SAMPLE * Digitalio::m_buffer_out = NULL; SAMPLE * Digitalio::m_buffer_in = NULL; SAMPLE ** Digitalio::m_write_ptr = NULL; SAMPLE ** Digitalio::m_read_ptr = NULL; SAMPLE * Digitalio::m_extern_in = NULL; SAMPLE * Digitalio::m_extern_out = NULL; BOOL__ Digitalio::m_out_ready = FALSE; BOOL__ Digitalio::m_in_ready = FALSE; BOOL__ Digitalio::m_use_cb = USE_CB_DEFAULT; DWORD__ Digitalio::m_go = 0; DWORD__ Digitalio::m_dac_n = 0; DWORD__ Digitalio::m_adc_n = 0; DWORD__ Digitalio::m_end = 0; DWORD__ Digitalio::m_block = TRUE; DWORD__ Digitalio::m_xrun = 0; // sample #if defined(CK_S_DOUBLE) #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT64 #else #define CK_RTAUDIO_FORMAT RTAUDIO_FLOAT32 #endif //----------------------------------------------------------------------------- // name: print() // desc: ... //----------------------------------------------------------------------------- void print( const RtAudioDeviceInfo & info ) { EM_error2b( 0, "device name = \"%s\"", info.name.c_str() ); if (info.probed == false) EM_error2b( 0, "probe [failed] ..." ); else { EM_error2b( 0, "probe [success] ..." ); EM_error2b( 0, "# output channels = %d", info.outputChannels ); EM_error2b( 0, "# input channels = %d", info.inputChannels ); EM_error2b( 0, "# duplex Channels = %d", info.duplexChannels ); if( info.isDefault ) EM_error2b( 0, "default device = YES" ); else EM_error2b( 0, "default device = NO" ); if( info.nativeFormats == 0 ) EM_error2b( 0, "no natively supported data formats(?)!" ); else { EM_error2b( 0, "natively supported data formats:" ); if( info.nativeFormats & RTAUDIO_SINT8 ) EM_error2b( 0, " 8-bit int" ); if( info.nativeFormats & RTAUDIO_SINT16 ) EM_error2b( 0, " 16-bit int" ); if( info.nativeFormats & RTAUDIO_SINT24 ) EM_error2b( 0, " 24-bit int" ); if( info.nativeFormats & RTAUDIO_SINT32 ) EM_error2b( 0, " 32-bit int" ); if( info.nativeFormats & RTAUDIO_FLOAT32 ) EM_error2b( 0, " 32-bit float" ); if( info.nativeFormats & RTAUDIO_FLOAT64 ) EM_error2b( 0, " 64-bit float" ); } if ( info.sampleRates.size() < 1 ) EM_error2b( 0,"no supported sample rates found!" ); else { EM_error2b( 0, "supported sample rates:" ); for( unsigned int j = 0; j < info.sampleRates.size(); j++ ) EM_error2b( 0, " %d Hz", info.sampleRates[j] ); } } } //----------------------------------------------------------------------------- // name: probe() // desc: ... //----------------------------------------------------------------------------- void Digitalio::probe() { RtAudio * rta = NULL; RtAudioDeviceInfo info; // allocate RtAudio try { rta = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2b( 0, "%s", err.getMessageString() ); return; } // get count int devices = rta->getDeviceCount(); EM_error2b( 0, "found %d device(s) ...", devices ); // EM_error2( 0, "--------------------------" ); // loop for( int i = 1; i <= devices; i++ ) { try { info = rta->getDeviceInfo(i); } catch( RtError & error ) { error.printMessage(); break; } // print EM_error2b( 0, "------( chuck -- dac%d )---------------", i ); print( info ); // skip if( i < devices ) EM_error2( 0, "" ); } delete rta; return; } #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) //----------------------------------------------------------------------------- // name: set_priority() // desc: ... //----------------------------------------------------------------------------- static t_CKBOOL set_priority( CHUCK_THREAD tid, t_CKINT priority ) { struct sched_param param; int policy; // log EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority ); // get for thread if( pthread_getschedparam( tid, &policy, ¶m) ) return FALSE; // priority param.sched_priority = priority; // policy policy = SCHED_RR; // set for thread if( pthread_setschedparam( tid, policy, ¶m ) ) return FALSE; return TRUE; } #else //----------------------------------------------------------------------------- // name: set_priority() // desc: ... //----------------------------------------------------------------------------- static t_CKBOOL set_priority( CHUCK_THREAD tid, t_CKINT priority ) { // if priority is 0 then done if( !priority ) return TRUE; // log EM_log( CK_LOG_FINE, "setting thread priority to: %ld...", priority ); // set the priority the thread if( !SetThreadPriority( tid, priority ) ) return FALSE; return TRUE; } #endif //----------------------------------------------------------------------------- // name: get_current_time() // desc: ... //----------------------------------------------------------------------------- static t_CKFLOAT get_current_time( t_CKBOOL fresh = TRUE ) { #ifdef __PLATFORM_WIN32__ struct _timeb t; _ftime(&t); return t.time + t.millitm/1000.0; #else static struct timeval t; if( fresh ) gettimeofday(&t,NULL); return t.tv_sec + (t_CKFLOAT)t.tv_usec/1000000; #endif return 0; } // watch dog globals static CHUCK_THREAD g_tid_synthesis = 0; static XThread * g_watchdog_thread = NULL; static t_CKBOOL g_watchdog_state = FALSE; static t_CKFLOAT g_watchdog_time = 0; //----------------------------------------------------------------------------- // name: watch_dog() // desc: ... //----------------------------------------------------------------------------- #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) static void * watch_dog( void * ) #else static unsigned int __stdcall watch_dog( void * ) #endif { t_CKFLOAT time; // boost priority? t_CKUINT priority = Chuck_VM::our_priority; // log EM_log( CK_LOG_SEVERE, "starting real-time watch dog processs..." ); // push log EM_pushlog(); EM_log( CK_LOG_INFO, "watchdog timeout: %f::second", g_watchdog_timeout ); EM_log( CK_LOG_INFO, "watchdog thread priority: %d", priority ); EM_log( CK_LOG_INFO, "watchdog countermeasure priority: %d", g_watchdog_countermeasure_priority ); // pop log EM_poplog(); // boost watchdog by same priority if( Chuck_VM::our_priority != 0x7fffffff ) Chuck_VM::set_priority( priority, NULL ); // while going while( g_do_watchdog ) { // get time = get_current_time( TRUE ); // fprintf( stderr, "last: %f now: %f\n", g_watchdog_time, time ); // resting if( g_watchdog_state == FALSE ) { // check xrun // if( Digitalio::m_xrun > 100 ) if( time - g_watchdog_time > g_watchdog_timeout ) { // log EM_log( CK_LOG_SEVERE, "real-time watchdog counter-measure activating..." ); // lowering priority if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff ) set_priority( g_tid_synthesis, g_watchdog_countermeasure_priority ); // set state g_watchdog_state = TRUE; } } else { // check xrun // if( Digitalio::m_xrun == 0 ) if( time - g_watchdog_time < g_watchdog_timeout ) { // log EM_log( CK_LOG_SEVERE, "real-time watchdog resting..." ); // raise priority if( g_tid_synthesis && Chuck_VM::our_priority != 0x7fffffff ) set_priority( g_tid_synthesis, Chuck_VM::our_priority ); // set state g_watchdog_state = FALSE; } } // advance time usleep( 40000 ); } // log EM_log( CK_LOG_SEVERE, "stopping real-time watch dog process..." ); return 0; } //----------------------------------------------------------------------------- // name: watchdog_start() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::watchdog_start() { // already if( g_watchdog_thread ) return FALSE; // flag g_do_watchdog = TRUE; // allocate it g_watchdog_thread = new XThread; // start it g_watchdog_thread->start( watch_dog, NULL ); return TRUE; } //----------------------------------------------------------------------------- // name: watchdog_stop() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::watchdog_stop() { // already if( !g_watchdog_thread ) return FALSE; // stop things g_do_watchdog = FALSE; // wait a bit // usleep( 100000 ) SAFE_DELETE( g_watchdog_thread ); return TRUE; } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::initialize( DWORD__ num_dac_channels, DWORD__ num_adc_channels, DWORD__ sampling_rate, DWORD__ bps, DWORD__ buffer_size, DWORD__ num_buffers, DWORD__ block, Chuck_VM * vm_ref, BOOL__ rt_audio, void * callback, void * data ) { if( m_init ) return FALSE; m_num_channels_out = num_dac_channels; m_num_channels_in = num_adc_channels; m_sampling_rate = sampling_rate; m_bps = bps; m_buffer_size = buffer_size; m_num_buffers = num_buffers; m_start = 0; m_tick_count = 0; m_go = 0; m_end = 0; m_block = block; DWORD__ num_channels; int bufsize = m_buffer_size; // if rt_audio is false, then set block to FALSE to avoid deadlock if( !rt_audio ) m_block = FALSE; // if real-time audio if( rt_audio ) { // allocate RtAudio try { m_rtaudio = new RtAudio( ); } catch( RtError err ) { // problem finding audio devices, most likely EM_error2( 0, "%s", err.getMessageString() ); return m_init = FALSE; } // log EM_log( CK_LOG_FINE, "initializing RtAudio..." ); // push indent EM_pushlog(); // open device try { // log EM_log( CK_LOG_FINE, "trying %d input %d output...", m_num_channels_in, m_num_channels_out ); // open RtAudio m_rtaudio->openStream( m_dac_n, m_num_channels_out, m_adc_n, m_num_channels_in, CK_RTAUDIO_FORMAT, sampling_rate, &bufsize, num_buffers ); // set callback if( m_use_cb ) { // log EM_log( CK_LOG_INFO, "initializing callback..." ); if( !callback ) { if( block ) m_rtaudio->setStreamCallback( &cb, vm_ref ); else m_rtaudio->setStreamCallback( &cb2, vm_ref ); } else { m_rtaudio->setStreamCallback( (RtAudioCallback)callback, data ); } } } catch( RtError err ) { // log EM_log( CK_LOG_INFO, "exception caught: '%s'...", err.getMessageString() ); EM_log( CK_LOG_INFO, "trying %d input %d output...", 0, m_num_channels_out ); try { bufsize = buffer_size; // try output only m_rtaudio->openStream( m_dac_n, m_num_channels_out, 0, 0, RTAUDIO_FLOAT32, sampling_rate, &bufsize, num_buffers ); // set callback if( m_use_cb ) { // log EM_log( CK_LOG_INFO, "initializing callback (again)..." ); if( !callback ) { if( block ) m_rtaudio->setStreamCallback( &cb, vm_ref ); else m_rtaudio->setStreamCallback( &cb2, vm_ref ); } else { m_rtaudio->setStreamCallback( (RtAudioCallback)callback, data ); } } } catch( RtError err ) { EM_error2( 0, "%s", err.getMessageString() ); SAFE_DELETE( m_rtaudio ); return m_init = FALSE; } } // check bufsize if( bufsize != (int)m_buffer_size ) { EM_log( CK_LOG_SEVERE, "new buffer size: %d -> %i", m_buffer_size, bufsize ); m_buffer_size = bufsize; } // pop indent EM_poplog(); } if( m_use_cb ) { num_channels = num_dac_channels > num_adc_channels ? num_dac_channels : num_adc_channels; // log EM_log( CK_LOG_SEVERE, "allocating buffers for %d x %d samples...", m_buffer_size, num_channels ); // allocate buffers m_buffer_in = new SAMPLE[m_buffer_size * num_channels]; m_buffer_out = new SAMPLE[m_buffer_size * num_channels]; memset( m_buffer_in, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); memset( m_buffer_out, 0, m_buffer_size * sizeof(SAMPLE) * num_channels ); m_read_ptr = NULL; m_write_ptr = NULL; } m_in_ready = FALSE; m_out_ready = FALSE; return m_init = TRUE; } //----------------------------------------------------------------------------- // name: cb() // desc: ... //----------------------------------------------------------------------------- int Digitalio::cb( char * buffer, int buffer_size, void * user_data ) { DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out; DWORD__ n = 20; DWORD__ start = 50; // copy input to local buffer if( m_num_channels_in ) { memcpy( m_buffer_in, buffer, len ); // copy to extern if( m_extern_in ) memcpy( m_extern_in, buffer, len ); } // flag ready m_in_ready = TRUE; // out is ready early if( m_go < start && m_go > 1 && m_out_ready ) m_go = start; // copy output into local buffer if( m_go >= start ) { while( !m_out_ready && n-- ) usleep( 250 ); if( m_out_ready && g_do_watchdog ) g_watchdog_time = get_current_time( TRUE ); // copy local buffer to be rendered if( m_out_ready && !m_end ) memcpy( buffer, m_buffer_out, len ); // set all elements of local buffer to silence else memset( buffer, 0, len ); } else // initial condition { // priority boost if( !m_go && Chuck_VM::our_priority != 0x7fffffff ) Chuck_VM::set_priority( Chuck_VM::our_priority, NULL ); // catch SIGINT // signal( SIGINT, signal_int ); // timestamp if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE ); memset( buffer, 0, len ); m_go++; return 0; } // 2nd buffer if( m_go == start ) { n = 8; while( !m_out_ready && n-- ) usleep( 250 ); len /= sizeof(SAMPLE); DWORD__ i = 0; SAMPLE * s = (SAMPLE *)buffer; while( i < len ) *s++ *= (SAMPLE)i++/len; m_go++; } // copy to extern if( m_extern_out ) memcpy( m_extern_out, buffer, len ); // set pointer to the beginning - if not ready, then too late anyway //*m_write_ptr = (SAMPLE *)m_buffer_out; //*m_read_ptr = (SAMPLE *)m_buffer_in; m_out_ready = FALSE; return 0; } //----------------------------------------------------------------------------- // name: cb2() // desc: ... //----------------------------------------------------------------------------- int Digitalio::cb2( char * buffer, int buffer_size, void * user_data ) { DWORD__ len = buffer_size * sizeof(SAMPLE) * m_num_channels_out; Chuck_VM * vm_ref = (Chuck_VM *)user_data; // priority boost if( !m_go && Chuck_VM::our_priority != 0x7fffffff ) { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) g_tid_synthesis = pthread_self(); #else // must duplicate for handle to be usable by other threads g_tid_synthesis = NULL; DuplicateHandle( GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_tid_synthesis, 0, FALSE, DUPLICATE_SAME_ACCESS ); // TODO: close the duplicate handle? #endif Chuck_VM::set_priority( Chuck_VM::our_priority, NULL ); memset( buffer, 0, len ); m_go = TRUE; // start watchdog if( g_do_watchdog ) { // timestamp g_watchdog_time = get_current_time( TRUE ); // start watchdog watchdog_start(); } // let it go the first time return 0; } // copy input to local buffer if( m_num_channels_in ) { memcpy( m_buffer_in, buffer, len ); // copy to extern if( m_extern_in ) memcpy( m_extern_in, buffer, len ); } // check xrun if( m_xrun < 6 ) { // timestamp if( g_do_watchdog ) g_watchdog_time = get_current_time( TRUE ); // get samples from output vm_ref->run( buffer_size ); // ... if( m_xrun ) m_xrun--; } else { // reset m_xrun /= 2; } // copy local buffer to be rendered if( !m_end ) memcpy( buffer, m_buffer_out, len ); // set all elements of local buffer to silence else memset( buffer, 0, len ); // copy to extern if( m_extern_out ) memcpy( m_extern_out, buffer, len ); return 0; } //----------------------------------------------------------------------------- // name: start() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::start( ) { try{ if( !m_start ) m_rtaudio->startStream(); m_start = TRUE; } catch( RtError err ){ return FALSE; } return m_start; } //----------------------------------------------------------------------------- // name: stop() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::stop( ) { try{ if( m_start ) m_rtaudio->stopStream(); m_start = FALSE; } catch( RtError err ){ return FALSE; } return !m_start; } //----------------------------------------------------------------------------- // name: tick() // desc: ... //----------------------------------------------------------------------------- BOOL__ Digitalio::tick( ) { try { if( ++m_tick_count >= m_start ) { m_rtaudio->tickStream(); m_tick_count = 0; m_out_ready = TRUE; m_in_ready = TRUE; } return TRUE; } catch( RtError err ){ return FALSE; } } //----------------------------------------------------------------------------- // name: shutdown() // desc: ... //----------------------------------------------------------------------------- void Digitalio::shutdown() { if( !m_init ) return; if( m_start ) { if( m_use_cb ) m_rtaudio->cancelStreamCallback(); m_rtaudio->stopStream(); } m_rtaudio->closeStream(); SAFE_DELETE( m_rtaudio ); m_init = FALSE; m_start = FALSE; // stop watchdog watchdog_stop(); } //----------------------------------------------------------------------------- // name: DigitalOut() // desc: ... //----------------------------------------------------------------------------- DigitalOut::DigitalOut() { m_data_ptr_out = NULL; m_data_max_out = NULL; } //----------------------------------------------------------------------------- // name: ~DigitalOut() // desc: ... //----------------------------------------------------------------------------- DigitalOut::~DigitalOut() { this->cleanup(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize audio out //----------------------------------------------------------------------------- BOOL__ DigitalOut::initialize( ) { // set pointer to beginning of local buffer m_data_ptr_out = Digitalio::m_use_cb ? Digitalio::m_buffer_out : (SAMPLE *)Digitalio::audio()->getStreamBuffer(); // calculate the end of the buffer m_data_max_out = m_data_ptr_out + Digitalio::buffer_size() * Digitalio::num_channels_out(); // set the writer pointer to our write pointer Digitalio::m_write_ptr = &m_data_ptr_out; return TRUE; } //----------------------------------------------------------------------------- // name: start() // desc: render //----------------------------------------------------------------------------- BOOL__ DigitalOut::start() { // start stream return ( Digitalio::start() != 0 ); } //----------------------------------------------------------------------------- // name: stop() // desc: render //----------------------------------------------------------------------------- BOOL__ DigitalOut::stop() { // well Digitalio::stop(); return TRUE; } //----------------------------------------------------------------------------- // name: cleanup() // desc: ... //----------------------------------------------------------------------------- void DigitalOut::cleanup() { } //----------------------------------------------------------------------------- // name: tick_out() // desc: 1 channel //----------------------------------------------------------------------------- BOOL__ DigitalOut::tick_out( SAMPLE sample ) { if( !prepare_tick_out() ) return FALSE; *m_data_ptr_out++ = sample; return TRUE; } //----------------------------------------------------------------------------- // name: tick_out() // desc: 2 channel //----------------------------------------------------------------------------- BOOL__ DigitalOut::tick_out( SAMPLE sample_l, SAMPLE sample_r ) { if( !prepare_tick_out() ) return FALSE; *m_data_ptr_out++ = sample_l; *m_data_ptr_out++ = sample_r; return TRUE; } //----------------------------------------------------------------------------- // name: tick_out() // desc: all channels //----------------------------------------------------------------------------- BOOL__ DigitalOut::tick_out( const SAMPLE * samples, DWORD__ n ) { if( !prepare_tick_out() ) return FALSE; if( !n ) n = Digitalio::m_num_channels_out; while( n-- ) *m_data_ptr_out++ = *samples++; return TRUE; } //----------------------------------------------------------------------------- // name: prepare_tick_out() // desc: data ptr ok //----------------------------------------------------------------------------- inline BOOL__ DigitalOut::prepare_tick_out() { if( m_data_ptr_out >= m_data_max_out ) { this->render(); } return TRUE; } //----------------------------------------------------------------------------- // name: render() // desc: the render //----------------------------------------------------------------------------- DWORD__ DigitalOut::render() { //if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE; if( Digitalio::m_block ) { // synchronize Digitalio::m_out_ready = TRUE; // synchronize while( Digitalio::m_out_ready ) usleep( 250 ); } // set pointer to the beginning - if not ready, then too late anyway *Digitalio::m_write_ptr = (SAMPLE *)Digitalio::m_buffer_out; return TRUE; } //----------------------------------------------------------------------------- // name: DigitalIn() // desc: ... //----------------------------------------------------------------------------- DigitalIn::DigitalIn() { m_data_ptr_in = NULL; m_data_max_in = NULL; } //----------------------------------------------------------------------------- // name: ~DigitalIn() // desc: ... //----------------------------------------------------------------------------- DigitalIn::~DigitalIn() { this->cleanup(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize audio in //----------------------------------------------------------------------------- BOOL__ DigitalIn::initialize( ) { m_data = new SAMPLE[Digitalio::buffer_size() * Digitalio::num_channels_in()]; memset( m_data, 0, Digitalio::buffer_size() * Digitalio::num_channels_in() * sizeof(SAMPLE) ); // set the buffer to the beginning of the local buffer m_data_ptr_in = Digitalio::m_use_cb ? m_data : (SAMPLE *)Digitalio::audio()->getStreamBuffer(); // calculate past buffer m_data_max_in = m_data_ptr_in + Digitalio::buffer_size() * Digitalio::num_channels_in(); // set the read pointer to the local pointer Digitalio::m_read_ptr = &m_data_ptr_in; // invalidate m_data_ptr_in = m_data_max_in; return TRUE; } //----------------------------------------------------------------------------- // name: start() // desc: ... //----------------------------------------------------------------------------- BOOL__ DigitalIn::start() { return ( Digitalio::start() != 0 ); } //----------------------------------------------------------------------------- // name: capture_stop() // desc: ... //----------------------------------------------------------------------------- BOOL__ DigitalIn::stop() { Digitalio::stop(); return TRUE; } //----------------------------------------------------------------------------- // name: cleanup() // desc: ... //----------------------------------------------------------------------------- void DigitalIn::cleanup() { } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ DigitalIn::tick_in( SAMPLE * s ) { if( !prepare_tick_in() ) return 0; *s = *m_data_ptr_in++; return TRUE; } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ DigitalIn::tick_in( SAMPLE * l, SAMPLE * r ) { if( !prepare_tick_in() ) return FALSE; *l = *m_data_ptr_in++; *r = *m_data_ptr_in++; return TRUE; } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ DigitalIn::tick_in( SAMPLE * sample, DWORD__ n ) { if( !prepare_tick_in() ) return FALSE; if( !n ) n = Digitalio::m_num_channels_in; while( n-- ) *sample++ = *m_data_ptr_in++; return TRUE; } //----------------------------------------------------------------------------- // name: prepare_tick_in() // desc: data ptr ok //----------------------------------------------------------------------------- inline BOOL__ DigitalIn::prepare_tick_in() { if( m_data_ptr_in >= m_data_max_in ) { this->capture(); } return TRUE; } //----------------------------------------------------------------------------- // name: cb_capture() // desc: ... //----------------------------------------------------------------------------- DWORD__ DigitalIn::capture( ) { // if( !Digitalio::m_use_cb && !Digitalio::tick() ) return FALSE; if( Digitalio::m_block ) { t_CKUINT n = 20; while( !Digitalio::m_in_ready && n-- ) usleep( 250 ); } // copy data memcpy( m_data, Digitalio::m_buffer_in, Digitalio::buffer_size() * Digitalio::num_channels_in() * sizeof(SAMPLE) ); Digitalio::m_in_ready = FALSE; // set pointer to the beginning - if not ready, then too late anyway *Digitalio::m_read_ptr = (SAMPLE *)m_data; return TRUE; } //----------------------------------------------------------------------------- // name: AudioBufferX() // desc: ... //----------------------------------------------------------------------------- AudioBufferX::AudioBufferX( DWORD__ size ) { if( size ) this->initialize( size ); else { m_size = size; m_data = m_ptr_curr = m_ptr_end = NULL; } } //----------------------------------------------------------------------------- // name: initialize() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferX::initialize( DWORD__ size ) { m_size = size; m_data = (SAMPLE *)malloc( size * sizeof(SAMPLE) ); if( !m_data ) return FALSE; // clear the memory memset( m_data, 0, size * sizeof(SAMPLE) ); // set the pointers m_ptr_curr = m_data; m_ptr_end = m_data + size; return TRUE; } //----------------------------------------------------------------------------- // name: cleanup() // desc: ... //----------------------------------------------------------------------------- void AudioBufferX::cleanup() { if( m_data ) { free( m_data ); m_data = NULL; } m_size = 0; m_ptr_curr = m_ptr_end = NULL; } //----------------------------------------------------------------------------- // name: size() // desc: ... //----------------------------------------------------------------------------- DWORD__ AudioBufferX::size() { return m_size; } //----------------------------------------------------------------------------- // name: data() // desc: ... //----------------------------------------------------------------------------- SAMPLE * AudioBufferX::data() { return m_data; } //----------------------------------------------------------------------------- // name: AudioBufferIn() // desc: ... //----------------------------------------------------------------------------- AudioBufferIn::AudioBufferIn( DWORD__ size ) : AudioBufferX( size ) { } //----------------------------------------------------------------------------- // name: ~AudioBufferIn() // desc: ... //----------------------------------------------------------------------------- AudioBufferIn::~AudioBufferIn() { this->cleanup(); } //----------------------------------------------------------------------------- // name: reset() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferIn::reset() { m_ptr_curr = m_data; return TickIn::reset(); } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferIn::tick_in( SAMPLE * s ) { if( !m_data ) return FALSE; *s = *m_ptr_curr++; return TRUE; } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferIn::tick_in( SAMPLE * l, SAMPLE * r ) { if( !m_data || m_ptr_curr + 2 >= m_ptr_end ) return FALSE; *l = *m_ptr_curr++; *r = *m_ptr_curr++; return TRUE; } //----------------------------------------------------------------------------- // name: tick_in() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferIn::tick_in( SAMPLE * in, DWORD__ n ) { if( !m_data || m_ptr_curr + n >= m_ptr_end ) return FALSE; while( n-- ) *in++ = *m_ptr_curr++; return TRUE; } //----------------------------------------------------------------------------- // name: AudioBufferOut() // desc: ... //----------------------------------------------------------------------------- AudioBufferOut::AudioBufferOut( DWORD__ size ) : AudioBufferX( size ) { } //----------------------------------------------------------------------------- // name: ~AudioBufferOut() // desc: ... //----------------------------------------------------------------------------- AudioBufferOut::~AudioBufferOut() { this->cleanup(); } //----------------------------------------------------------------------------- // name: reset() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferOut::reset() { m_ptr_curr = m_data; return TickOut::reset(); } //----------------------------------------------------------------------------- // name: tick_out() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferOut::tick_out( SAMPLE s ) { if( !m_data ) return FALSE; *m_ptr_curr++ = s; return TRUE; } //----------------------------------------------------------------------------- // name: tick_out() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferOut::tick_out( SAMPLE l, SAMPLE r ) { if( !m_data || m_ptr_curr + 2 >= m_ptr_end ) return FALSE; *m_ptr_curr++ = l; *m_ptr_curr++ = r; return TRUE; } //----------------------------------------------------------------------------- // name: tick_out() // desc: ... //----------------------------------------------------------------------------- BOOL__ AudioBufferOut::tick_out( const SAMPLE * out, DWORD__ n ) { if( !m_data || m_ptr_curr + n >= m_ptr_end ) return FALSE; while( n-- ) *m_ptr_curr++ = *out++; return TRUE; } chuck-1.2.0.8.dfsg/src/digiio_rtaudio.h0000644000175000017500000002350110600421721016272 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: digiio_rtaudio.h // desc: digitalio over RtAudio (from Gary Scavone) // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __DIGITAL_IO_H__ #define __DIGITAL_IO_H__ #include "chuck_def.h" //----------------------------------------------------------------------------- // define and forward references //----------------------------------------------------------------------------- // #ifndef SAFE_DELETE // #define SAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } } // #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p); (p)=NULL; } } // #endif // defaults #if defined(__MACOSX_CORE__) #define BUFFER_SIZE_DEFAULT 256 #else #define BUFFER_SIZE_DEFAULT 512 #endif #define NUM_BUFFERS_DEFAULT 8 #define NUM_CHANNELS_DEFAULT 2 // number of channels #if defined(__LINUX_ALSA__ ) || defined(__LINUX_OSS__) || defined(__LINUX_JACK__) #define SAMPLING_RATE_DEFAULT 48000 // sampling rate #define USE_CB_DEFAULT TRUE // callback #else #define SAMPLING_RATE_DEFAULT 44100 // sampling rate #define USE_CB_DEFAULT TRUE // callback #endif #define BITS_PER_SAMPLE_DEFAULT 16 // sample size #define DEVICE_NUM_OUT_DEFAULT 0 #define DEVICE_NUM_IN_DEFAULT 0 // sample types // #define SAMPLE_SHORT short // #define SAMPLE_INTERNAL SAMPLE_SHORT // #define SAMPLE float // #define S_MAX 0x7fff // max value for 16 bit // #define S_MIN -0x7fff // min value for 16 bit // external to internal sample conversion // #define SAMPLE_TO_INTERNAL(s) ( (SAMPLE_INTERNAL)((SAMPLE)S_MAX * s) ) // #define INTERNAL_TO_SAMPLE(s) ( (SAMPLE)((SAMPLE)s / S_MAX) ) // types #define BOOL__ DWORD__ #define DWORD__ unsigned long #define SINT__ long #define UINT__ DWORD__ #define BYTE__ unsigned char #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif class RtAudio; struct Chuck_VM; //----------------------------------------------------------------------------- // name: Digitalio // desc: ... //----------------------------------------------------------------------------- class Digitalio { public: static BOOL__ initialize( DWORD__ num_dac_channels = NUM_CHANNELS_DEFAULT, DWORD__ num_adc_channels = NUM_CHANNELS_DEFAULT, DWORD__ sampling_rate = SAMPLING_RATE_DEFAULT, DWORD__ bps = BITS_PER_SAMPLE_DEFAULT, DWORD__ buffer_size = BUFFER_SIZE_DEFAULT, DWORD__ num_buffers = NUM_BUFFERS_DEFAULT, DWORD__ block = TRUE, Chuck_VM * vm_ref = NULL, BOOL__ rt_audio = TRUE, void * callback = NULL, void * data = NULL ); static BOOL__ watchdog_start(); static BOOL__ watchdog_stop(); static void shutdown(); static void probe(); public: static DWORD__ sampling_rate( ) { return m_sampling_rate; } static DWORD__ num_channels_out( ) { return m_num_channels_out; } static DWORD__ num_channels_in( ) { return m_num_channels_in; } static DWORD__ bps( ) { return m_bps; } static DWORD__ buffer_size( ) { return m_buffer_size; } static DWORD__ num_buffers( ) { return m_num_buffers; } static RtAudio * audio( ) { return m_rtaudio; } static BOOL__ start( ); static BOOL__ stop( ); static BOOL__ tick( ); static void set_extern( SAMPLE * in, SAMPLE * out ) { m_extern_in = in; m_extern_out = out; } static int cb( char * buffer, int buffer_size, void * user_data ); static int cb2( char * buffer, int buffer_size, void * user_data ); public: // data static BOOL__ m_init; static DWORD__ m_start; static DWORD__ m_tick_count; static DWORD__ m_num_channels_out; static DWORD__ m_num_channels_in; static DWORD__ m_sampling_rate; static DWORD__ m_bps; static DWORD__ m_buffer_size; static DWORD__ m_num_buffers; static RtAudio * m_rtaudio; static SAMPLE * m_buffer_out; static SAMPLE * m_buffer_in; static SAMPLE ** m_write_ptr; static SAMPLE ** m_read_ptr; static SAMPLE * m_extern_in; static SAMPLE * m_extern_out; static BOOL__ m_out_ready; static BOOL__ m_in_ready; static BOOL__ m_use_cb; static DWORD__ m_go; static DWORD__ m_end; static DWORD__ m_block; static DWORD__ m_xrun; static DWORD__ m_dac_n; static DWORD__ m_adc_n; }; //----------------------------------------------------------------------------- // name: TickOut // desc: ... //----------------------------------------------------------------------------- class TickOut { public: virtual ~TickOut() {} public: virtual BOOL__ reset() { return true; } virtual BOOL__ tick_out( SAMPLE s ) = 0; virtual BOOL__ tick_out( SAMPLE l, SAMPLE r ) = 0; virtual BOOL__ tick_out( const SAMPLE * out, DWORD__ n ) = 0; }; //----------------------------------------------------------------------------- // name: TickIn // desc: ... //----------------------------------------------------------------------------- class TickIn { public: virtual ~TickIn() { } public: virtual BOOL__ reset() { return true; } virtual BOOL__ tick_in( SAMPLE * in ) = 0; virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r ) = 0; virtual BOOL__ tick_in( SAMPLE * in, DWORD__ n ) = 0; virtual SAMPLE tick( ) { SAMPLE in; return ( tick_in( &in ) ? in : (SAMPLE)0.0f ); } }; //----------------------------------------------------------------------------- // name: class DigitalOut // desc: ... //----------------------------------------------------------------------------- class DigitalOut : public TickOut { public: DigitalOut(); ~DigitalOut(); public: BOOL__ initialize(); void cleanup(); BOOL__ start(); BOOL__ stop(); public: virtual BOOL__ tick_out( SAMPLE s ); virtual BOOL__ tick_out( SAMPLE l, SAMPLE r ); virtual BOOL__ tick_out( const SAMPLE * samples, DWORD__ n ); public: DWORD__ render(); protected: SAMPLE * m_data_ptr_out; SAMPLE * m_data_max_out; inline BOOL__ prepare_tick_out(); }; //----------------------------------------------------------------------------- // name: class DigitalIn // desc: ... //----------------------------------------------------------------------------- class DigitalIn : public TickIn { public: DigitalIn(); ~DigitalIn(); public: // in BOOL__ initialize(); void cleanup(); BOOL__ start(); BOOL__ stop(); public: virtual BOOL__ tick_in( SAMPLE * s ); virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r ); virtual BOOL__ tick_in( SAMPLE * samples, DWORD__ n ); public: DWORD__ capture( ); protected: SAMPLE * m_data; SAMPLE * m_data_ptr_in; SAMPLE * m_data_max_in; inline BOOL__ prepare_tick_in(); }; //----------------------------------------------------------------------------- // name: AudioBufferX // desc: ... //----------------------------------------------------------------------------- class AudioBufferX { public: AudioBufferX( DWORD__ size = 0 ); public: BOOL__ initialize( DWORD__ size ); void cleanup(); SAMPLE * data(); DWORD__ size(); protected: SAMPLE * m_data; DWORD__ m_size; SAMPLE * m_ptr_curr; SAMPLE * m_ptr_end; }; //----------------------------------------------------------------------------- // name: AudioBufferIn // desc: ... //----------------------------------------------------------------------------- class AudioBufferIn : public TickIn, public AudioBufferX { public: AudioBufferIn( DWORD__ size = 0 ); virtual ~AudioBufferIn(); public: virtual BOOL__ reset(); virtual BOOL__ tick_in( SAMPLE * in ); virtual BOOL__ tick_in( SAMPLE * l, SAMPLE * r ); virtual BOOL__ tick_in( SAMPLE * in, DWORD__ n ); }; //----------------------------------------------------------------------------- // name: AudioBufferOut // desc: ... //----------------------------------------------------------------------------- class AudioBufferOut : public TickOut, public AudioBufferX { public: AudioBufferOut( DWORD__ size = 0 ); virtual ~AudioBufferOut(); public: virtual BOOL__ reset(); virtual BOOL__ tick_out( SAMPLE s ); virtual BOOL__ tick_out( SAMPLE l, SAMPLE r ); virtual BOOL__ tick_out( const SAMPLE * out, DWORD__ n ); }; #endif chuck-1.2.0.8.dfsg/src/hidio_sdl.cpp0000644000175000017500000005643410600421721015603 0ustar piempiem /*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: hidio_sdl.cpp // desc: HID io over SDL // // author: Spencer Salazar (ssalazar@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: spring 2006 //----------------------------------------------------------------------------- #include "hidio_sdl.h" #include "util_hid.h" #include "chuck_errmsg.h" #ifndef __PLATFORM_WIN32__ #include #else #include "chuck_def.h" #endif #include #include #include using namespace std; static Chuck_Hid_Driver default_drivers[CK_HID_DEV_COUNT]; struct PhyHidDevIn { public: PhyHidDevIn(); ~PhyHidDevIn(); t_CKBOOL open( t_CKINT type, t_CKUINT number ); t_CKBOOL read( t_CKINT element_type, t_CKINT element_num, HidMsg * msg ); t_CKBOOL send( const HidMsg * msg ); t_CKBOOL close(); std::string name(); t_CKBOOL query_element( HidMsg * query ); t_CKBOOL register_client( HidIn * client ); t_CKBOOL unregister_client( HidIn * client ); public: CBufferAdvance * cbuf; protected: t_CKINT device_type; t_CKUINT device_num; std::vector< HidIn * > clients; }; struct PhyHidDevOut { // lies }; //----------------------------------------------------------------------------- // global variables //----------------------------------------------------------------------------- // per-physical device buffer size #define BUFFER_SIZE 8192 std::vector< std::vector > HidInManager::the_matrix; XThread * HidInManager::the_thread = NULL; t_CKBOOL HidInManager::thread_going = FALSE; t_CKBOOL HidInManager::has_init = FALSE; CBufferSimple * HidInManager::msg_buffer = NULL; std::vector HidOutManager::the_phouts; //----------------------------------------------------------------------------- // name: PhyHidDevIn() // desc: constructor //----------------------------------------------------------------------------- PhyHidDevIn::PhyHidDevIn() { device_type = CK_HID_DEV_NONE; device_num = 0; cbuf = NULL; } //----------------------------------------------------------------------------- // name: ~PhyHidDevIn() // desc: destructor //----------------------------------------------------------------------------- PhyHidDevIn::~PhyHidDevIn() { // check if( device_type != CK_HID_DEV_NONE ) this->close(); } //----------------------------------------------------------------------------- // name: open() // desc: opens the device of specified type and id //----------------------------------------------------------------------------- t_CKBOOL PhyHidDevIn::open( t_CKINT type, t_CKUINT number ) { // int temp; // check if( device_type != CK_HID_DEV_NONE ) { // log EM_log( CK_LOG_WARNING, "PhyHidDevIn: open() failed -> already open!" ); return FALSE; } if( type <= CK_HID_DEV_NONE || type >= CK_HID_DEV_COUNT ) { // log EM_log( CK_LOG_WARNING, "PhyHidDevIn: open() failed -> invalid device type %d", type ); return FALSE; } if( !default_drivers[type].open ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: open() failed -> %s does not support open", default_drivers[type].driver_name ); return FALSE; } if( default_drivers[type].open( ( int ) number ) ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: open() failed -> invalid %s number %d", default_drivers[type].driver_name, number ); return FALSE; } // allocate the buffer cbuf = new CBufferAdvance; if( !cbuf->initialize( BUFFER_SIZE, sizeof(HidMsg) ) ) { // log EM_log( CK_LOG_WARNING, "PhyHidDevIn: open operation failed: cannot initialize buffer" ); this->close(); return FALSE; } device_type = type; device_num = number; return TRUE; } //----------------------------------------------------------------------------- // name: read() // desc: query specific elements of the hid device //----------------------------------------------------------------------------- t_CKBOOL PhyHidDevIn::read( t_CKINT element_type, t_CKINT element_num, HidMsg * msg ) { if( !default_drivers[device_type].read ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: read() failed -> %s does not support read", default_drivers[device_type].driver_name ); return FALSE; } if( default_drivers[device_type].read( device_num, element_type, element_num, msg ) ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: read() failed for %s %i, element type %i, element number %i", default_drivers[device_type].driver_name, device_num, element_type, element_num ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: send() // desc: send message to a HID device //----------------------------------------------------------------------------- t_CKBOOL PhyHidDevIn::send( const HidMsg * msg ) { if( !default_drivers[device_type].send ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: send() failed -> %s does not support send", default_drivers[device_type].driver_name ); return FALSE; } if( default_drivers[device_type].send( device_num, msg ) ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: send() failed for %s %i", default_drivers[device_type].driver_name, device_num ); return FALSE; } return TRUE; } //----------------------------------------------------------------------------- // name: close() // desc: closes the device, deallocates all associated data //----------------------------------------------------------------------------- t_CKBOOL PhyHidDevIn::close() { // check if( cbuf != NULL ) { // delete SAFE_DELETE( cbuf ); // TODO: release references from cbuf? } if( device_type <= CK_HID_DEV_NONE || device_type >= CK_HID_DEV_COUNT ) { // log EM_log( CK_LOG_WARNING, "PhyHidDevIn: close() failed -> invalid device type %d", device_type ); return FALSE; } if( !default_drivers[device_type].close ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: close() failed -> %s does not support close", default_drivers[device_type].driver_name ); return FALSE; } if( default_drivers[device_type].close( ( int ) device_num ) ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: close() failed -> invalid %s number %d", default_drivers[device_type].driver_name, device_num ); return FALSE; } device_type = CK_HID_DEV_NONE; device_num = 0; return TRUE; } //----------------------------------------------------------------------------- // name: name() // desc: retrieve device name //----------------------------------------------------------------------------- string PhyHidDevIn::name() { if( device_type == CK_HID_DEV_NONE ) return " "; if( device_type <= CK_HID_DEV_NONE || device_type >= CK_HID_DEV_COUNT ) { // log EM_log( CK_LOG_WARNING, "PhyHidDevIn: name() failed -> invalid device type %d", device_type ); return " "; } if( !default_drivers[device_type].name ) return default_drivers[device_type].driver_name; const char * _name; if( !( _name = default_drivers[device_type].name( ( int ) device_num ) ) ) { EM_log( CK_LOG_WARNING, "PhyHidDevIn: name() failed -> invalid %s number %d", default_drivers[device_type].driver_name, device_num ); return " "; } return _name; } //----------------------------------------------------------------------------- // name: HidOut() // desc: constructor //----------------------------------------------------------------------------- HidOut::HidOut() { // phout = new PhyHidDevOut; m_device_num = 0; m_valid = FALSE; m_suppress_output = FALSE; } //----------------------------------------------------------------------------- // name: ~HidOut() // desc: destructor //----------------------------------------------------------------------------- HidOut::~HidOut() { if( phout ) this->close(); SAFE_DELETE( phout ); } //----------------------------------------------------------------------------- // name: send() // desc: send //----------------------------------------------------------------------------- t_CKUINT HidOut::send( const HidMsg * msg ) { if( !m_valid ) return 0; return 0; } //----------------------------------------------------------------------------- // name: open // desc: open HID output //----------------------------------------------------------------------------- t_CKBOOL HidOut::open( t_CKUINT device_num ) { // close if already opened if( m_valid ) this->close(); return m_valid = HidOutManager::open( this, (t_CKINT)device_num ); } //----------------------------------------------------------------------------- // name: close( ) // desc: close HID output //----------------------------------------------------------------------------- t_CKBOOL HidOut::close( ) { if( !m_valid ) return FALSE; // close // HidOutManager::close( this ); m_valid = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: HidIn() // desc: constructor //----------------------------------------------------------------------------- HidIn::HidIn() { phin = NULL; m_device_num = 0; m_valid = FALSE; m_read_index = 0; m_buffer = NULL; m_suppress_output = FALSE; SELF = NULL; } //----------------------------------------------------------------------------- // name: ~HidIn() // desc: destructor //----------------------------------------------------------------------------- HidIn::~HidIn( ) { this->close(); // SAFE_DELETE( min ); } //----------------------------------------------------------------------------- // name: open() // desc: open //----------------------------------------------------------------------------- t_CKBOOL HidIn::open( t_CKINT device_type, t_CKINT device_num ) { // close if already opened if( m_valid ) this->close(); // open return m_valid = HidInManager::open( this, device_type, device_num ); } void HidInManager::init() { // log EM_log( CK_LOG_INFO, "initializing HID..." ); EM_pushlog(); if( has_init == FALSE ) { init_default_drivers(); // allocate the matrix the_matrix.resize( CK_HID_DEV_COUNT ); // resize each vector for( vector >::size_type i = 0; i < the_matrix.size(); i++ ) { // allocate the_matrix[i].resize( CK_MAX_HID_DEVICES ); } msg_buffer = new CBufferSimple; msg_buffer->initialize( 1000, sizeof( HidMsg ) ); #ifndef __MACOSX_CORE__ Hid_init(); #endif // __MACOSX_CORE__ for( size_t j = 0; j < CK_HID_DEV_COUNT; j++ ) { if( default_drivers[j].init ) default_drivers[j].init(); } has_init = TRUE; } EM_poplog(); } void HidInManager::init_default_drivers() { memset( default_drivers, 0, CK_HID_DEV_COUNT * sizeof( Chuck_Hid_Driver ) ); default_drivers[CK_HID_DEV_JOYSTICK].init = Joystick_init; default_drivers[CK_HID_DEV_JOYSTICK].quit = Joystick_quit; default_drivers[CK_HID_DEV_JOYSTICK].count = Joystick_count; default_drivers[CK_HID_DEV_JOYSTICK].open = Joystick_open; default_drivers[CK_HID_DEV_JOYSTICK].close = Joystick_close; default_drivers[CK_HID_DEV_JOYSTICK].name = Joystick_name; default_drivers[CK_HID_DEV_JOYSTICK].driver_name = "joystick"; default_drivers[CK_HID_DEV_MOUSE].init = Mouse_init; default_drivers[CK_HID_DEV_MOUSE].quit = Mouse_quit; default_drivers[CK_HID_DEV_MOUSE].count = Mouse_count; default_drivers[CK_HID_DEV_MOUSE].open = Mouse_open; default_drivers[CK_HID_DEV_MOUSE].close = Mouse_close; default_drivers[CK_HID_DEV_MOUSE].name = Mouse_name; default_drivers[CK_HID_DEV_MOUSE].driver_name = "mouse"; default_drivers[CK_HID_DEV_KEYBOARD].init = Keyboard_init; default_drivers[CK_HID_DEV_KEYBOARD].quit = Keyboard_quit; default_drivers[CK_HID_DEV_KEYBOARD].count = Keyboard_count; default_drivers[CK_HID_DEV_KEYBOARD].open = Keyboard_open; default_drivers[CK_HID_DEV_KEYBOARD].close = Keyboard_close; default_drivers[CK_HID_DEV_KEYBOARD].send = Keyboard_send; default_drivers[CK_HID_DEV_KEYBOARD].name = Keyboard_name; default_drivers[CK_HID_DEV_KEYBOARD].driver_name = "keyboard"; default_drivers[CK_HID_DEV_WIIREMOTE].init = WiiRemote_init; default_drivers[CK_HID_DEV_WIIREMOTE].quit = WiiRemote_quit; default_drivers[CK_HID_DEV_WIIREMOTE].count = WiiRemote_count; default_drivers[CK_HID_DEV_WIIREMOTE].open = WiiRemote_open; default_drivers[CK_HID_DEV_WIIREMOTE].close = WiiRemote_close; default_drivers[CK_HID_DEV_WIIREMOTE].send = WiiRemote_send; default_drivers[CK_HID_DEV_WIIREMOTE].name = WiiRemote_name; default_drivers[CK_HID_DEV_WIIREMOTE].driver_name = "wii remote"; default_drivers[CK_HID_DEV_TILTSENSOR].init = TiltSensor_init; default_drivers[CK_HID_DEV_TILTSENSOR].quit = TiltSensor_quit; default_drivers[CK_HID_DEV_TILTSENSOR].count = TiltSensor_count; default_drivers[CK_HID_DEV_TILTSENSOR].open = TiltSensor_open; default_drivers[CK_HID_DEV_TILTSENSOR].close = TiltSensor_close; default_drivers[CK_HID_DEV_TILTSENSOR].read = TiltSensor_read; default_drivers[CK_HID_DEV_TILTSENSOR].name = TiltSensor_name; default_drivers[CK_HID_DEV_TILTSENSOR].driver_name = "tilt sensor"; } void HidInManager::cleanup() { // log EM_log( CK_LOG_INFO, "shutting down HID..." ); if( has_init ) { // loop for( vector >::size_type i = 0; i < the_matrix.size(); i++ ) { // loop for( vector::size_type j = 0; j < the_matrix[i].size(); j++ ) { // deallocate devices SAFE_DELETE( the_matrix[i][j] ); } } // flag thread_going = FALSE; // break Hid_poll(); Hid_quit(); // clean up if( the_thread != NULL ) SAFE_DELETE( the_thread ); // clean up subsystems for( size_t j = 0; j < CK_HID_DEV_COUNT; j++ ) { if( default_drivers[j].quit ) default_drivers[j].quit(); } if( msg_buffer ) { msg_buffer->cleanup(); SAFE_DELETE( msg_buffer ); } // init has_init = FALSE; //*/ } } t_CKBOOL HidInManager::open( HidIn * hin, t_CKINT device_type, t_CKINT device_num ) { // init? if( has_init == FALSE ) { init(); } // check type if( device_type < 1 || device_type >= CK_HID_DEV_COUNT ) { // log EM_log( CK_LOG_WARNING, "HidInManager: open() failed -> invalid type '%d'...", device_type ); return FALSE; } // start thread if( the_thread == NULL ) { // allocate the_thread = new XThread; // flag thread_going = TRUE; // start the_thread->start( cb_hid_input, NULL ); } // get the vector vector & v = the_matrix[device_type]; // see if port not already open if( device_num >= (t_CKINT)v.capacity() || !v[device_num] ) { // allocate PhyHidDevIn * phin = new PhyHidDevIn; // open if( !phin->open( device_type, device_num ) ) { // log // should this use EM_log instead, with a higher log level? EM_error2( 0, "HidIn: couldn't open %s %d...", default_drivers[device_type].driver_name, device_num ); SAFE_DELETE( phin ); return FALSE; } // resize? if( device_num >= (t_CKINT)v.capacity() ) { t_CKINT size = v.capacity() * 2; if( device_num >= size ) size = device_num + 1; v.resize( size ); } // put cbuf and rtmin in vector for future generations v[device_num] = phin; } // set min hin->phin = v[device_num]; // found hin->m_buffer = v[device_num]->cbuf; // get an index into your (you are min here) own buffer, // and a free ticket to your own workshop hin->m_read_index = hin->m_buffer->join( (Chuck_Event *)hin->SELF ); hin->m_device_num = (t_CKUINT)device_num; // done return TRUE; } //----------------------------------------------------------------------------- // name: close() // desc: close //----------------------------------------------------------------------------- t_CKBOOL HidIn::close() { if( !m_valid ) return FALSE; // close //HidInManager::close( this ); m_valid = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: empty() // desc: is empty? //----------------------------------------------------------------------------- t_CKBOOL HidIn::empty() { if( !m_valid ) return TRUE; return m_buffer->empty( m_read_index ); } //----------------------------------------------------------------------------- // name: recv() // desc: receive message //----------------------------------------------------------------------------- t_CKUINT HidIn::recv( HidMsg * msg ) { if( !m_valid ) return FALSE; return m_buffer->get( msg, 1, m_read_index ); } //----------------------------------------------------------------------------- // name: read() // desc: read //----------------------------------------------------------------------------- t_CKBOOL HidIn::read( t_CKINT type, t_CKINT num, HidMsg * msg ) { if( !m_valid || !phin ) return FALSE; // do read return phin->read( type, num, msg ); } //----------------------------------------------------------------------------- // name: send() // desc: send //----------------------------------------------------------------------------- t_CKBOOL HidIn::send( const HidMsg * msg ) { if( !m_valid || !phin ) return FALSE; // do send return phin->send( msg ); } //----------------------------------------------------------------------------- // name: name() // desc: get device name //----------------------------------------------------------------------------- std::string HidIn::name() { if( m_valid && phin ) return phin->name(); return " "; } //----------------------------------------------------------------------------- // name: cb_hid_input // desc: called by device implementations to push a message onto the buffer //----------------------------------------------------------------------------- void HidInManager::push_message( HidMsg & msg ) { // find the queue if( the_matrix[msg.device_type][msg.device_num] != NULL ) { CBufferAdvance * cbuf = the_matrix[msg.device_type][msg.device_num]->cbuf; if( cbuf != NULL ) // queue the thing cbuf->put( &msg, 1 ); } } extern "C" void push_message( HidMsg msg ) { HidInManager::push_message( msg ); } //----------------------------------------------------------------------------- // name: cb_hid_input // desc: call back //----------------------------------------------------------------------------- #ifndef __PLATFORM_WIN32__ void * HidInManager::cb_hid_input( void * stuff ) #else unsigned __stdcall HidInManager::cb_hid_input( void * stuff ) #endif { #ifdef __MACOSX_CORE__ Hid_init(); #endif // keep going while( thread_going ) { Hid_poll(); } // log EM_log( CK_LOG_INFO, "HID thread exiting..." ); return 0; } //----------------------------------------------------------------------------- // name: probeHidIn() // desc: ... //----------------------------------------------------------------------------- void HidInManager::probeHidIn() { if( !has_init ) { for( size_t i = 0; i < CK_HID_DEV_COUNT; i++ ) { if( default_drivers[i].init && default_drivers[i].probe ) default_drivers[i].init(); } } for( size_t i = 0; i < CK_HID_DEV_COUNT; i++ ) { if( default_drivers[i].probe ) default_drivers[i].probe(); } if( !has_init ) { for( size_t i = 0; i < CK_HID_DEV_COUNT; i++ ) { if( default_drivers[i].quit ) default_drivers[i].quit(); } } } //----------------------------------------------------------------------------- // name: probeHidOut() // desc: ... //----------------------------------------------------------------------------- void HidInManager::probeHidOut() { } HidOutManager::HidOutManager() { the_phouts.resize( 1024 ); } HidOutManager::~HidOutManager() { // yeah right } t_CKBOOL HidOutManager::open( HidOut * hout, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_phouts.capacity() || !the_phouts[device_num] ) { // allocate PhyHidDevOut * phout = new PhyHidDevOut; // resize? if( device_num >= (t_CKINT)the_phouts.capacity() ) { t_CKINT size = the_phouts.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_phouts.resize( size ); } // put rtmout in vector for future generations the_phouts[device_num] = phout; } // found (always) (except when it doesn't get here) hout->phout = the_phouts[device_num]; hout->m_device_num = (t_CKUINT)device_num; // done return TRUE; } chuck-1.2.0.8.dfsg/src/hidio_sdl.h0000644000175000017500000001103010600421721015227 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: hidio_sdl.h // desc: HID io over SDL header // // author: Spencer Salazar (ssalazar@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #ifndef __HID_IO_H__ #define __HID_IO_H__ #include "chuck_def.h" #include "util_buffers.h" #include "util_thread.h" #include "util_hid.h" // forward reference struct PhyHidDevIn; struct PhyHidDevOut; /* constants */ #define CK_MAX_HID_DEVICES 1024 //----------------------------------------------------------------------------- // name: struct HidOut // desc: HID out //----------------------------------------------------------------------------- class HidOut { public: HidOut(); ~HidOut(); public: t_CKBOOL open( t_CKUINT device_num = 0 ); t_CKBOOL close(); t_CKBOOL good() { return m_valid; } t_CKINT num() { return m_valid ? (t_CKINT)m_device_num : -1; } public: void set_suppress( t_CKBOOL print_or_not ) { m_suppress_output = print_or_not; } t_CKBOOL get_suppress() { return m_suppress_output; } public: t_CKUINT send( const HidMsg * msg ); public: PhyHidDevOut * phout; std::vector m_msg; t_CKUINT m_device_num; t_CKBOOL m_valid; t_CKBOOL m_suppress_output; }; //----------------------------------------------------------------------------- // name: class HidIn // desc: HID input //----------------------------------------------------------------------------- struct HidIn : public Chuck_Event { public: HidIn(); ~HidIn(); public: t_CKBOOL open( t_CKINT device_type, t_CKINT device_num ); t_CKBOOL close(); t_CKBOOL read( t_CKINT type, t_CKINT num, HidMsg * msg ); t_CKBOOL send( const HidMsg * msg ); t_CKBOOL good() { return m_valid; } t_CKINT num() { return m_valid ? (t_CKINT)m_device_num : -1; } public: void set_suppress( t_CKBOOL print_or_not ) { m_suppress_output = print_or_not; } t_CKBOOL get_suppress() { return m_suppress_output; } public: t_CKBOOL empty(); t_CKUINT recv( HidMsg * msg ); std::string name(); public: PhyHidDevIn * phin; CBufferAdvance * m_buffer; t_CKUINT m_read_index; t_CKBOOL m_valid; t_CKINT m_device_num; Chuck_Object * SELF; t_CKBOOL m_suppress_output; }; class HidInManager { public: static void init(); static void init_default_drivers(); static void cleanup(); static t_CKBOOL open( HidIn * hin, t_CKINT device_type, t_CKINT device_num ); static t_CKBOOL close( HidIn * hin ); static void probeHidIn(); static void probeHidOut(); #ifndef __PLATFORM_WIN32__ static void * cb_hid_input( void * ); #else static unsigned __stdcall cb_hid_input( void * ); #endif static void push_message( HidMsg & msg ); protected: static std::vector< std::vector > the_matrix; static XThread * the_thread; static CBufferSimple * msg_buffer; static t_CKBOOL thread_going; static t_CKBOOL has_init; }; class HidOutManager { public: static t_CKBOOL open( HidOut * hout, t_CKINT device_num ); static t_CKBOOL close( HidOut * hout ); protected: HidOutManager(); ~HidOutManager(); static std::vector the_phouts; }; #endif chuck-1.2.0.8.dfsg/src/makefile0000644000175000017500000000135110600421721014625 0ustar piempiemDESTDIR=/usr/bin current: @echo "[chuck build]: please use one of the following configurations:"; echo " make linux-alsa, make linux-jack, make linux-oss,"; echo " make osx, make osx-ub, or make win32" install: cp $(wildcard chuck chuck.exe) $(DESTDIR)/ chmod 755 $(DESTDIR)/$(wildcard chuck chuck.exe) osx: -make -f makefile.osx osx-ppc: -make -f makefile.osx osx-intel: -make -f makefile.osx # Mac OS X universal binary osx-ub: -make -f makefile.osx-ub linux-oss: -make -f makefile.oss linux-jack: -make -f makefile.jack linux-alsa: -make -f makefile.alsa win32: -make -f makefile.win32 osx-rl: -make -f makefile.rl clean: rm -f *.o chuck.tab.c chuck.tab.h chuck.yy.c chuck.output $(wildcard chuck chuck.exe) chuck-1.2.0.8.dfsg/src/makefile.alsa0000644000175000017500000001266410612371371015565 0ustar piempiemCC?=gcc CXX?=g++ LEX=flex YACC=bison INCLUDES= CFLAGS?= -O3 FLAGS= -D__LINUX_ALSA__ -c $(CFLAGS) LIBS=-lasound -lstdc++ -ldl -lm SF_OBJ=util_sndfile.o ifneq ($(CHUCK_DEBUG),) FLAGS+= -g -O0 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK on linux needs libsndfile... # comment the next 3 lines to use a pre-configured libsndfile #----------------------------------------------------------------------------- FLAGS+= -D__CK_SNDFILE_NATIVE__ LIBS+= -lsndfile SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ util_buffers.o util_console.o util_string.o util_thread.o \ util_math.o util_network.o util_raw.o util_xforms.o \ util_hid.o $(SF_OBJ) chuck: $(OBJS) $(CXX) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CC) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CC) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_scan.h chuck_scan.cpp chuck_type.h $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp $(CXX) $(FLAGS) util_console.cpp util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp util_math.o: util_math.h util_math.c $(CC) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CC) $(FLAGS) util_network.c util_raw.o: util_raw.h util_raw.c $(CC) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CC) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CC) $(FLAGS) util_sndfile.c clean: rm -f chuck *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c chuck-1.2.0.8.dfsg/src/makefile.jack0000644000175000017500000001267610612371467015566 0ustar piempiem CC?=gcc CXX?=g++ LEX=flex YACC=bison INCLUDES= CFLAGS?= -O3 FLAGS= -D__LINUX_JACK__ -c $(CFLAGS) LIBS=-lasound -ljack -lstdc++ -ldl -lm SF_OBJ=util_sndfile.o ifneq ($(CHUCK_DEBUG),) FLAGS+= -g -O0 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK on linux needs on libsndfile... # comment the next 3 lines to use pre-configured libsndfile #----------------------------------------------------------------------------- FLAGS+= -D__CK_SNDFILE_NATIVE__ LIBS+= -lsndfile SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ util_buffers.o util_console.o util_string.o util_thread.o \ util_math.o util_network.o util_raw.o util_xforms.o \ util_hid.o $(SF_OBJ) chuck: $(OBJS) $(CXX) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CC) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CC) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_scan.h chuck_scan.cpp chuck_type.h $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp $(CXX) $(FLAGS) util_console.cpp util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp util_math.o: util_math.h util_math.c $(CC) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CC) $(FLAGS) util_network.c util_raw.o: util_raw.h util_raw.c $(CC) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CC) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CC) $(FLAGS) util_sndfile.c clean: rm -f chuck *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c chuck-1.2.0.8.dfsg/src/makefile.oss0000644000175000017500000001266510612371431015447 0ustar piempiem CC?=gcc CXX?=g++ LEX=flex YACC=bison INCLUDES= CFLAGS?= -O3 FLAGS= -D__LINUX_OSS__ -c $(CFLAGS) LIBS=-lpthread -lstdc++ -ldl -lm SF_OBJ=util_sndfile.o ifneq ($(CHUCK_DEBUG),) FLAGS+= -g -O0 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK on linux needs libsndfile... # comment the next 3 lines to use a pre-configured libsndfile #----------------------------------------------------------------------------- FLAGS+= -D__CK_SNDFILE_NATIVE__ LIBS+= -lsndfile SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ util_buffers.o util_console.o util_string.o util_thread.o \ util_math.o util_network.o util_raw.o util_xforms.o \ util_hid.o $(SF_OBJ) chuck: $(OBJS) $(CXX) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CC) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CC) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_scan.h chuck_scan.cpp chuck_type.h $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp $(CXX) $(FLAGS) util_console.cpp util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp util_math.o: util_math.h util_math.c $(CC) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CC) $(FLAGS) util_network.c util_raw.o: util_raw.h util_raw.c $(CC) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CC) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CC) $(FLAGS) util_sndfile.c clean: rm -f chuck *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c chuck-1.2.0.8.dfsg/src/makefile.osx0000644000175000017500000001342210600421721015437 0ustar piempiem CXX=gcc CXX_LINK=g++ LEX=flex YACC=bison INCLUDES= FLAGS=-D__MACOSX_CORE__ -c LIBS=-framework CoreAudio -framework CoreMIDI -framework CoreFoundation \ -framework IOKit -framework Carbon -lstdc++ -lm SF_OBJ=util_sndfile.o ifneq ($(CHUCK_STAT),) FLAGS+= -D__CHUCK_STAT_TRACK__ endif ifneq ($(CHUCK_DEBUG),) FLAGS+= -g else FLAGS+= -O3 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK uses a pre-configured libsndfile... # uncomment the next 3 lines to use libsndfile on your system #----------------------------------------------------------------------------- #FLAGS+= -D__CK_SNDFILE_NATIVE__ #LIBS+= -lsndfile #SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ ulib_opsc.o util_buffers.o util_console.o util_math.o util_network.o \ util_raw.o util_string.o util_thread.o util_xforms.o util_opsc.o \ util_hid.o $(SF_OBJ) chuck: $(OBJS) $(CXX_LINK) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CXX) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_type.h chuck_scan.h chuck_scan.cpp $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp ulib_opsc.o: ulib_opsc.h ulib_opsc.cpp $(CXX) $(FLAGS) ulib_opsc.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp chuck_shell.h $(CXX) $(FLAGS) util_console.cpp util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp util_math.o: util_math.h util_math.c $(CXX) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CXX) $(FLAGS) util_network.c util_opsc.o: util_opsc.h util_opsc.cpp $(CXX) $(FLAGS) util_opsc.cpp util_raw.o: util_raw.h util_raw.c $(CXX) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CXX) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CXX) $(FLAGS) util_sndfile.c clean: rm -f chuck *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c chuck-1.2.0.8.dfsg/src/makefile.osx-ub0000644000175000017500000001365610600421721016054 0ustar piempiem CXX=gcc CXX_LINK=g++ LEX=flex YACC=bison INCLUDES= FLAGS=-D__MACOSX_CORE__ -D__MACOSX_UB__ -c -arch ppc -arch i386 \ -isysroot /Developer/SDKs/MacOSX10.4u.sdk LIBS=-framework CoreAudio -framework CoreMIDI -framework CoreFoundation \ -framework IOKit -framework Carbon -lstdc++ -lm \ -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk SF_OBJ=util_sndfile.o ifneq ($(CHUCK_STAT),) FLAGS+= -D__CHUCK_STAT_TRACK__ endif ifneq ($(CHUCK_DEBUG),) FLAGS+= -g else FLAGS+= -O3 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK uses a pre-configured libsndfile... # uncomment the next 3 lines to use libsndfile on your system #----------------------------------------------------------------------------- #FLAGS+= -D__CK_SNDFILE_NATIVE__ #LIBS+= -lsndfile #SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ ulib_opsc.o util_buffers.o util_console.o util_math.o util_network.o \ util_raw.o util_string.o util_thread.o util_xforms.o util_opsc.o \ util_hid.o $(SF_OBJ) chuck: $(OBJS) $(CXX_LINK) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CXX) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_type.h chuck_scan.h chuck_scan.cpp $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp ulib_opsc.o: ulib_opsc.h ulib_opsc.cpp $(CXX) $(FLAGS) ulib_opsc.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp chuck_shell.h $(CXX) $(FLAGS) util_console.cpp util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp util_math.o: util_math.h util_math.c $(CXX) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CXX) $(FLAGS) util_network.c util_opsc.o: util_opsc.h util_opsc.cpp $(CXX) $(FLAGS) util_opsc.cpp util_raw.o: util_raw.h util_raw.c $(CXX) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CXX) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CXX) $(FLAGS) util_sndfile.c clean: rm -f chuck *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c chuck-1.2.0.8.dfsg/src/makefile.win320000644000175000017500000001345310600421721015574 0ustar piempiem CXX=gcc LEX=flex YACC=bison INCLUDES=-I/usr/include/directx/ FLAGS=-D__WINDOWS_DS__ -D__WINDOWS_PTHREAD__ $(INCLUDES) -c LIBS=-ldsound -ldinput -ldxguid -lwinmm -lstdc++ -lm -lole32 SF_OBJ=util_sndfile.o ifneq ($(CHUCK_DEBUG),) FLAGS+= -g else FLAGS+= -O3 endif ifneq ($(CHUCK_STRICT),) FLAGS+= -Wall endif #----------------------------------------------------------------------------- # by default, ChucK uses a pre-configured libsndfile... # uncomment the next 3 lines to use libsndfile on your system #----------------------------------------------------------------------------- #FLAGS+= -D__CK_SNDFILE_NATIVE__ #LIBS+= -lsndfile #SF_OBJ= OBJS= chuck.tab.o chuck.yy.o chuck_absyn.o chuck_parse.o chuck_errmsg.o \ chuck_frame.o chuck_symbol.o chuck_table.o chuck_utils.o \ chuck_vm.o chuck_instr.o chuck_scan.o chuck_type.o chuck_emit.o \ chuck_compile.o chuck_dl.o chuck_oo.o chuck_lang.o chuck_ugen.o \ chuck_main.o chuck_otf.o chuck_stats.o chuck_bbq.o chuck_shell.o \ chuck_console.o chuck_globals.o digiio_rtaudio.o hidio_sdl.o \ midiio_rtmidi.o rtaudio.o rtmidi.o ugen_osc.o ugen_filter.o \ ugen_stk.o ugen_xxx.o ulib_machine.o ulib_math.o ulib_std.o \ ulib_opsc.o util_buffers.o util_console.o util_math.o util_network.o \ util_raw.o util_string.o util_thread.o util_xforms.o util_opsc.o \ util_hid.o \ $(SF_OBJ) chuck: $(OBJS) $(CXX) -o chuck $(OBJS) $(LIBS) chuck.tab.o: chuck.tab.c $(CXX) $(FLAGS) chuck.tab.c chuck.tab.c: chuck.y $(YACC) -dv -b chuck chuck.y chuck.tab.h: chuck.tab.c echo "chuck.tab.h was created at the same time as chuck.tab.c" chuck.yy.o: chuck.yy.c chuck.tab.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck.yy.c chuck.yy.c: chuck.lex $(LEX) -ochuck.yy.c chuck.lex chuck_absyn.o: chuck_absyn.cpp chuck_absyn.h chuck_utils.h chuck_symbol.h $(CXX) $(FLAGS) chuck_absyn.cpp chuck_parse.o: chuck_parse.h chuck_parse.cpp $(CXX) $(FLAGS) chuck_parse.cpp chuck_scan.o: chuck_scan.h chuck_scan.cpp chuck_type.h $(CXX) $(FLAGS) chuck_scan.cpp chuck_type.o: chuck_type.cpp chuck_type.h chuck_absyn.h chuck_oo.h chuck_vm.h chuck_instr.h $(CXX) $(FLAGS) chuck_type.cpp chuck_emit.o: chuck_emit.cpp chuck_emit.h chuck_type.h chuck_instr.h chuck_vm.h $(CXX) $(FLAGS) chuck_emit.cpp chuck_compile.o: chuck_compile.h chuck_compile.cpp $(CXX) $(FLAGS) chuck_compile.cpp chuck_symbol.o: chuck_symbol.cpp chuck_symbol.h chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_symbol.cpp chuck_frame.o: chuck_frame.h chuck_frame.cpp $(CXX) $(FLAGS) chuck_frame.cpp chuck_errmsg.o: chuck_errmsg.cpp chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_errmsg.cpp chuck_utils.o: chuck_utils.cpp chuck_utils.h $(CXX) $(FLAGS) chuck_utils.cpp chuck_table.o: chuck_table.cpp chuck_table.h chuck_utils.h $(CXX) $(FLAGS) chuck_table.cpp chuck_instr.o: chuck_instr.h chuck_instr.cpp chuck_type.h chuck_vm.h $(CXX) $(FLAGS) chuck_instr.cpp chuck_vm.o: chuck_vm.h chuck_vm.cpp chuck_instr.h chuck_oo.h chuck_type.h $(CXX) $(FLAGS) chuck_vm.cpp chuck_oo.o: chuck_oo.h chuck_oo.cpp $(CXX) $(FLAGS) chuck_oo.cpp chuck_lang.o: chuck_lang.h chuck_lang.cpp chuck_oo.h $(CXX) $(FLAGS) chuck_lang.cpp chuck_ugen.o: chuck_ugen.cpp chuck_ugen.h chuck_def.h $(CXX) $(FLAGS) chuck_ugen.cpp chuck_dl.o: chuck_dl.h chuck_dl.cpp $(CXX) $(FLAGS) chuck_dl.cpp chuck_otf.o: chuck_otf.h chuck_otf.cpp $(CXX) $(FLAGS) chuck_otf.cpp chuck_stats.o: chuck_stats.h chuck_stats.cpp $(CXX) $(FLAGS) chuck_stats.cpp chuck_bbq.o: chuck_bbq.cpp chuck_bbq.h midiio_rtmidi.h $(CXX) $(FLAGS) chuck_bbq.cpp chuck_shell.o: chuck_shell.h chuck_shell.cpp $(CXX) $(FLAGS) chuck_shell.cpp chuck_console.o: chuck_console.h chuck_console.cpp $(CXX) $(FLAGS) chuck_console.cpp chuck_globals.o: chuck_globals.h chuck_globals.cpp $(CXX) $(FLAGS) chuck_globals.cpp chuck_main.o: chuck_main.cpp chuck_absyn.h chuck_type.h chuck_emit.h chuck_vm.h chuck_errmsg.h chuck_utils.h $(CXX) $(FLAGS) chuck_main.cpp digiio_rtaudio.o: digiio_rtaudio.h digiio_rtaudio.cpp rtaudio.h $(CXX) $(FLAGS) digiio_rtaudio.cpp hidio_sdl.o: hidio_sdl.h hidio_sdl.cpp $(CXX) $(FLAGS) hidio_sdl.cpp midiio_rtmidi.o: midiio_rtmidi.h midiio_rtmidi.cpp $(CXX) $(FLAGS) midiio_rtmidi.cpp rtaudio.o: rtaudio.h rtaudio.cpp rterror.h $(CXX) $(FLAGS) rtaudio.cpp rtmidi.o: rtmidi.h rtmidi.cpp $(CXX) $(FLAGS) rtmidi.cpp ugen_osc.o: ugen_osc.h ugen_osc.cpp $(CXX) $(FLAGS) ugen_osc.cpp ugen_xxx.o: ugen_xxx.h ugen_xxx.cpp $(CXX) $(FLAGS) ugen_xxx.cpp ugen_filter.o: ugen_filter.h ugen_filter.cpp $(CXX) $(FLAGS) ugen_filter.cpp ugen_stk.o: ugen_stk.h ugen_stk.cpp $(CXX) $(FLAGS) ugen_stk.cpp ulib_machine.o: ulib_machine.h ulib_machine.cpp $(CXX) $(FLAGS) ulib_machine.cpp ulib_math.o: ulib_math.h ulib_math.cpp $(CXX) $(FLAGS) ulib_math.cpp ulib_std.o: ulib_std.h ulib_std.cpp $(CXX) $(FLAGS) ulib_std.cpp ulib_opsc.o: ulib_opsc.h ulib_opsc.cpp $(CXX) $(FLAGS) ulib_opsc.cpp util_buffers.o: util_buffers.h util_buffers.cpp $(CXX) $(FLAGS) util_buffers.cpp util_console.o: util_console.h util_console.cpp $(CXX) $(FLAGS) util_console.cpp util_math.o: util_math.h util_math.c $(CXX) $(FLAGS) util_math.c util_network.o: util_network.h util_network.c $(CXX) $(FLAGS) util_network.c util_opsc.o: util_opsc.h util_opsc.cpp $(CXX) $(FLAGS) util_opsc.cpp util_raw.o: util_raw.h util_raw.c $(CXX) $(FLAGS) util_raw.c util_string.o: util_string.h util_string.cpp $(CXX) $(FLAGS) util_string.cpp util_thread.o: util_thread.h util_thread.cpp $(CXX) $(FLAGS) util_thread.cpp util_xforms.o: util_xforms.h util_xforms.c $(CXX) $(FLAGS) util_xforms.c util_sndfile.o: util_sndfile.h util_sndfile.c $(CXX) $(FLAGS) util_sndfile.c util_hid.o: util_hid.h util_hid.cpp $(CXX) $(FLAGS) util_hid.cpp clean: rm -f chuck.exe *~ *.o chuck.output chuck.tab.h chuck.tab.c chuck.yy.c parse: chuck.tab.h chuck.tab.c chuck.yy.c cp chuck.tab.h chuck_win32.h; cat chuck.tab.c chuck.yy.c > chuck_win32.c chuck-1.2.0.8.dfsg/src/midiio_rtmidi.cpp0000644000175000017500000004724310600421721016465 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: midiio_rtmidi.cpp // desc: midi io // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: summer 2005 //----------------------------------------------------------------------------- #include "midiio_rtmidi.h" #include "chuck_errmsg.h" #include #include #include //----------------------------------------------------------------------------- // global variables //----------------------------------------------------------------------------- #define BUFFER_SIZE 8192 std::vector MidiInManager::the_mins; std::vector MidiInManager::the_bufs; std::vector MidiOutManager::the_mouts; //----------------------------------------------------------------------------- // name: MidiOut() // desc: constructor //----------------------------------------------------------------------------- MidiOut::MidiOut() { mout = new RtMidiOut; m_device_num = 0; m_valid = FALSE; m_suppress_output = FALSE; } //----------------------------------------------------------------------------- // name: ~MidiOut() // desc: destructor //----------------------------------------------------------------------------- MidiOut::~MidiOut() { if( mout ) this->close(); SAFE_DELETE( mout ); } //----------------------------------------------------------------------------- // name: send() // desc: send 1 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status ) { return this->send( status, 0, 0 ); } //----------------------------------------------------------------------------- // name: send() // desc: send 2 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1 ) { return this->send( status, data1, 0 ); } //----------------------------------------------------------------------------- // name: send() // desc: send 3 byte midi message //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( t_CKBYTE status, t_CKBYTE data1, t_CKBYTE data2 ) { if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( status ); m_msg.push_back( data1 ); m_msg.push_back( data2 ); mout->sendMessage( &m_msg ); return 3; } //----------------------------------------------------------------------------- // name: send() // desc: send //----------------------------------------------------------------------------- t_CKUINT MidiOut::send( const MidiMsg * msg ) { if( !m_valid ) return 0; // clear m_msg.clear(); // add m_msg.push_back( msg->data[0] ); m_msg.push_back( msg->data[1] ); m_msg.push_back( msg->data[2] ); mout->sendMessage( &m_msg ); return 3; } //----------------------------------------------------------------------------- // name: open // desc: open midi output //----------------------------------------------------------------------------- t_CKBOOL MidiOut::open( t_CKUINT device_num ) { // close if already opened if( m_valid ) this->close(); return m_valid = MidiOutManager::open( this, (t_CKINT)device_num ); } //----------------------------------------------------------------------------- // name: close( ) // desc: close midi output //----------------------------------------------------------------------------- t_CKBOOL MidiOut::close( ) { if( !m_valid ) return FALSE; // close // MidiOutManager::close( this ); m_valid = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: noteon() // desc: note on message //----------------------------------------------------------------------------- t_CKUINT MidiOut::noteon( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ) { return this->send( (t_CKBYTE)(MIDI_NOTEON + channel), note, velocity ); } //----------------------------------------------------------------------------- // name: noteoff() // desc: note off message //----------------------------------------------------------------------------- t_CKUINT MidiOut::noteoff( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ) { return this->send( (t_CKBYTE)(MIDI_NOTEOFF + channel), note, velocity ); } //----------------------------------------------------------------------------- // name: polypress() // desc: polypress message //----------------------------------------------------------------------------- t_CKUINT MidiOut::polypress( t_CKUINT channel, t_CKUINT note, t_CKUINT pressure ) { return this->send( (t_CKBYTE)(MIDI_POLYPRESS + channel), note, pressure ); } //----------------------------------------------------------------------------- // name: ctrlchange() // desc: ctrl change message //----------------------------------------------------------------------------- t_CKUINT MidiOut::ctrlchange( t_CKUINT channel, t_CKUINT ctrl_num, t_CKUINT ctrl_val ) { return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), ctrl_num, ctrl_val ); } //----------------------------------------------------------------------------- // name: progchange() // desc: prog change message //----------------------------------------------------------------------------- t_CKUINT MidiOut::progchange( t_CKUINT channel, t_CKUINT patch ) { return this->send( (t_CKBYTE)(MIDI_PROGCHANGE + channel), patch, 0 ); } //----------------------------------------------------------------------------- // name: chanpress() // desc: chan press //----------------------------------------------------------------------------- t_CKUINT MidiOut::chanpress( t_CKUINT channel, t_CKUINT pressure ) { return this->send( (t_CKBYTE)(MIDI_CHANPRESS + channel), pressure, 0 ); } //----------------------------------------------------------------------------- // name: pitchbend() // desc: pitch bend //----------------------------------------------------------------------------- t_CKUINT MidiOut::pitchbend( t_CKUINT channel, t_CKUINT bend_val ) { assert( FALSE ); return 0; // return this->send( (t_CKBYTE)(MIDI_PITCHBEND + channel), // (t_CKBYTE)(HIBYTE( bend_val << 1 )), // (t_CKBYTE)(LOBYTE( bend_val & 0x7f )) ); } //----------------------------------------------------------------------------- // name: allnotesoff() // desc: allnotesoff //----------------------------------------------------------------------------- t_CKUINT MidiOut::allnotesoff( t_CKUINT channel ) { return this->send( (t_CKBYTE)(MIDI_CTRLCHANGE + channel), (t_CKBYTE)(MIDI_ALLNOTESOFF), 0 ); } //----------------------------------------------------------------------------- // name: MidiIn() // desc: constructor //----------------------------------------------------------------------------- MidiIn::MidiIn() { min = NULL; m_device_num = 0; m_valid = FALSE; m_read_index = 0; m_buffer = NULL; m_suppress_output = FALSE; SELF = NULL; } //----------------------------------------------------------------------------- // name: ~MidiIn() // desc: destructor //----------------------------------------------------------------------------- MidiIn::~MidiIn( ) { this->close(); // SAFE_DELETE( min ); } //----------------------------------------------------------------------------- // name: open() // desc: open //----------------------------------------------------------------------------- t_CKBOOL MidiIn::open( t_CKUINT device_num ) { // close if already opened if( m_valid ) this->close(); // open return m_valid = MidiInManager::open( this, (t_CKINT)device_num ); } MidiInManager::MidiInManager() { the_mins.resize( 1024 ); the_bufs.resize( 1024 ); } MidiInManager::~MidiInManager() { // yeah right } t_CKBOOL MidiInManager::open( MidiIn * min, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_mins.capacity() || !the_mins[device_num] ) { // allocate the buffer CBufferAdvance * cbuf = new CBufferAdvance; if( !cbuf->initialize( BUFFER_SIZE, sizeof(MidiMsg) ) ) { if( !min->m_suppress_output ) EM_error2( 0, "MidiIn: couldn't allocate CBuffer for port %i...", device_num ); delete cbuf; return FALSE; } // allocate RtMidiIn * rtmin = new RtMidiIn; try { rtmin->openPort( device_num ); rtmin->setCallback( cb_midi_input, cbuf ); } catch( RtError & err ) { if( !min->m_suppress_output ) { // print it EM_error2( 0, "MidiIn: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } delete cbuf; return FALSE; } // resize? if( device_num >= (t_CKINT)the_mins.capacity() ) { t_CKINT size = the_mins.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mins.resize( size ); the_bufs.resize( size ); } // put cbuf and rtmin in vector for future generations the_mins[device_num] = rtmin; the_bufs[device_num] = cbuf; } // set min min->min = the_mins[device_num]; // found min->m_buffer = the_bufs[device_num]; // get an index into your (you are min here) own buffer, // and a free ticket to your own workshop min->m_read_index = min->m_buffer->join( (Chuck_Event *)min->SELF ); min->m_device_num = (t_CKUINT)device_num; // done return TRUE; } //----------------------------------------------------------------------------- // name: close() // desc: close //----------------------------------------------------------------------------- t_CKBOOL MidiIn::close() { if( !m_valid ) return FALSE; // close // MidiInManager::close( this ); m_valid = FALSE; return TRUE; } //----------------------------------------------------------------------------- // name: empty() // desc: is empty? //----------------------------------------------------------------------------- t_CKBOOL MidiIn::empty() { if( !m_valid ) return TRUE; return m_buffer->empty( m_read_index ); } //----------------------------------------------------------------------------- // name: get() // desc: get message //----------------------------------------------------------------------------- t_CKUINT MidiIn::recv( MidiMsg * msg ) { if( !m_valid ) return FALSE; return m_buffer->get( msg, 1, m_read_index ); } //----------------------------------------------------------------------------- // name: cb_midi_output // desc: call back //----------------------------------------------------------------------------- void MidiInManager::cb_midi_input( double deltatime, std::vector * msg, void * userData ) { unsigned int nBytes = msg->size(); CBufferAdvance * cbuf = (CBufferAdvance *)userData; MidiMsg m; if( nBytes >= 1 ) m.data[0] = msg->at(0); if( nBytes >= 2 ) m.data[1] = msg->at(1); if( nBytes >= 3 ) m.data[2] = msg->at(2); // put in the buffer, make sure not active sensing if( m.data[2] != 0xfe ) { cbuf->put( &m, 1 ); } } //----------------------------------------------------------------------------- // name: probeMidiIn() // desc: ... //----------------------------------------------------------------------------- void probeMidiIn() { RtMidiIn * min = NULL; try { min = new RtMidiIn;; } catch( RtError & err ) { EM_error2b( 0, "%s", err.getMessageString() ); return; } // get num t_CKUINT num = min->getPortCount(); EM_error2b( 0, "------( chuck -- %i MIDI inputs )------", num ); std::string s; for( t_CKUINT i = 0; i < num; i++ ) { try { s = min->getPortName( i ); } catch( RtError & err ) { err.printMessage(); return; } EM_error2b( 0, " [%i] : \"%s\"", i, s.c_str() ); } } //----------------------------------------------------------------------------- // name: probeMidiOut() // desc: ... //----------------------------------------------------------------------------- void probeMidiOut() { RtMidiOut * mout = NULL; try { mout = new RtMidiOut; } catch( RtError & err ) { EM_error2b( 0, "%s", err.getMessageString() ); return; } // get num t_CKUINT num = mout->getPortCount(); EM_error2b( 0, "------( chuck -- %i MIDI outputs )-----", num ); std::string s; for( t_CKUINT i = 0; i < num; i++ ) { try { s = mout->getPortName( i ); } catch( RtError & err ) { err.printMessage(); return; } EM_error2b( 0, " [%i] : \"%s\"", i, s.c_str() ); } } MidiOutManager::MidiOutManager() { the_mouts.resize( 1024 ); } MidiOutManager::~MidiOutManager() { // yeah right } t_CKBOOL MidiOutManager::open( MidiOut * mout, t_CKINT device_num ) { // see if port not already open if( device_num >= (t_CKINT)the_mouts.capacity() || !the_mouts[device_num] ) { // allocate RtMidiOut * rtmout = new RtMidiOut; try { rtmout->openPort( device_num ); } catch( RtError & err ) { if( !mout->m_suppress_output ) { // print it EM_error2( 0, "MidiOut: couldn't open MIDI port %i...", device_num ); err.getMessage(); // const char * e = err.getMessage().c_str(); // EM_error2( 0, "...(%s)", err.getMessage().c_str() ); } return FALSE; } // resize? if( device_num >= (t_CKINT)the_mouts.capacity() ) { t_CKINT size = the_mouts.capacity() * 2; if( device_num >= size ) size = device_num + 1; the_mouts.resize( size ); } // put rtmout in vector for future generations the_mouts[device_num] = rtmout; } // found (always) (except when it doesn't get here) mout->mout = the_mouts[device_num]; mout->m_device_num = (t_CKUINT)device_num; // done return TRUE; } //----------------------------------------------------------------------------- // name: class MidiRW // desc: reads and writes midi messages from file //----------------------------------------------------------------------------- static std::map g_rw; t_CKBOOL out_detach( ); t_CKBOOL midirw_detach( ) { std::map::iterator iter; std::vector list; // log EM_log( CK_LOG_INFO, "detaching MIDI devices..." ); for( iter = g_rw.begin(); iter != g_rw.end(); iter++ ) list.push_back( (*iter).second ); for( t_CKUINT i = 0; i < list.size(); i++ ) list[i]->close(); // TODO: release the MidiRW g_rw.clear(); return out_detach( ); } MidiRW::MidiRW() { file = NULL; } MidiRW::~MidiRW() { this->close(); } t_CKBOOL MidiRW::open( const char * filename ) { this->close(); file = fopen( filename, "rb+" ); if( file == NULL ) { file = fopen( filename, "wb+" ); } // add to hash g_rw[this] = this; return ( file != NULL ); } t_CKBOOL MidiRW::close() { if( !file ) return FALSE; t_CKBOOL value = fclose( file ) == 0; // remove from hash std::map::iterator iter; iter = g_rw.find( this ); g_rw.erase( iter ); file = NULL; return value; } t_CKBOOL MidiRW::read( MidiMsg * msg, t_CKTIME * time ) { if( !file ) return FALSE; // is it open? i don't know... t_CKBOOL m, t; // wouldn't it be cool if this worked? m = fread( msg, sizeof(MidiMsg), 1, file ); t = fread( time, sizeof(t_CKTIME), 1, file ); return m && t; } t_CKBOOL MidiRW::write( MidiMsg * msg, t_CKTIME * time ) { if( !file ) return FALSE; t_CKBOOL m, t; m = fwrite( msg, sizeof(MidiMsg), 1, file ); t = fwrite( time, sizeof(t_CKTIME), 1, file ); fflush( file ); return m && t; } //----------------------------------------------------------------------------- // name: class MidiMsgOut // desc: writes midi messages from file //----------------------------------------------------------------------------- static std::map g_out; t_CKBOOL out_detach( ) { std::map::iterator iter; std::vector list; for( iter = g_out.begin(); iter != g_out.end(); iter++ ) list.push_back( (*iter).second ); for( t_CKUINT i = 0; i < list.size(); i++ ) list[i]->close(); return TRUE; } MidiMsgOut::MidiMsgOut() { file = NULL; } MidiMsgOut::~MidiMsgOut() { this->close(); } t_CKBOOL MidiMsgOut::open( const char * filename ) { this->close(); file = fopen( filename, "wb" ); // add to hash g_out[this] = this; return ( file != NULL ); } t_CKBOOL MidiMsgOut::close() { if( !file ) return FALSE; t_CKBOOL value = fclose( file ) == 0; // remove from hash std::map::iterator iter; iter = g_out.find( this ); g_out.erase( iter ); file = NULL; return value; } t_CKBOOL MidiMsgOut::write( MidiMsg * msg, t_CKTIME * time ) { if( !file ) return FALSE; t_CKBOOL m, t; m = fwrite( msg, sizeof(MidiMsg), 1, file ); t = fwrite( time, sizeof(t_CKTIME), 1, file ); fflush( file ); return m && t; } //----------------------------------------------------------------------------- // name: class MidiMsgIn // desc: reads midi messages from file //----------------------------------------------------------------------------- MidiMsgIn::MidiMsgIn() { file = NULL; } MidiMsgIn::~MidiMsgIn() { this->close(); } t_CKBOOL MidiMsgIn::open( const char * filename ) { this->close(); file = fopen( filename, "rb" ); return ( file != NULL ); } t_CKBOOL MidiMsgIn::close() { if( !file ) return FALSE; t_CKBOOL value = fclose( file ) == 0; file = NULL; return value; } t_CKBOOL MidiMsgIn::read( MidiMsg * msg, t_CKTIME * time ) { if( !file ) return FALSE; // is it open? i don't know... t_CKBOOL m, t; // wouldn't it be cool if this worked? m = fread( msg, sizeof(MidiMsg), 1, file ); t = fread( time, sizeof(t_CKTIME), 1, file ); return m && t; } chuck-1.2.0.8.dfsg/src/midiio_rtmidi.h0000644000175000017500000001544410600421721016130 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: midiio_rtmidi.h // desc: midi io header // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #ifndef __MIDI_IO_H__ #define __MIDI_IO_H__ #include "chuck_def.h" #include "rtmidi.h" #include "util_buffers.h" //----------------------------------------------------------------------------- // stuff //----------------------------------------------------------------------------- #define MIDI_NOTEON 0x90 #define MIDI_NOTEOFF 0x80 #define MIDI_POLYPRESS 0xa0 #define MIDI_CTRLCHANGE 0xb0 #define MIDI_PROGCHANGE 0xc0 #define MIDI_CHANPRESS 0xd0 #define MIDI_PITCHBEND 0xe0 #define MIDI_ALLNOTESOFF 0x7b //----------------------------------------------------------------------------- // definitions //----------------------------------------------------------------------------- union MidiMsg { t_CKBYTE data[4]; // t_CKUINT dw; }; //----------------------------------------------------------------------------- // name: class MidiOut // desc: midi out //----------------------------------------------------------------------------- class MidiOut { public: MidiOut(); ~MidiOut(); public: t_CKBOOL open( t_CKUINT device_num = 0 ); t_CKBOOL close(); t_CKBOOL good() { return m_valid; } t_CKINT num() { return m_valid ? (t_CKINT)m_device_num : -1; } public: void set_suppress( t_CKBOOL print_or_not ) { m_suppress_output = print_or_not; } t_CKBOOL get_suppress() { return m_suppress_output; } public: t_CKUINT send( t_CKBYTE status ); t_CKUINT send( t_CKBYTE status, t_CKBYTE data1 ); t_CKUINT send( t_CKBYTE status, t_CKBYTE data1, t_CKBYTE data2 ); t_CKUINT send( const MidiMsg * msg ); public: t_CKUINT noteon( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ); t_CKUINT noteoff( t_CKUINT channel, t_CKUINT note, t_CKUINT velocity ); t_CKUINT polypress( t_CKUINT channel, t_CKUINT note, t_CKUINT pressure ); t_CKUINT ctrlchange( t_CKUINT channel, t_CKUINT ctrl_num, t_CKUINT ctrl_val ); t_CKUINT progchange( t_CKUINT channel, t_CKUINT patch ); t_CKUINT chanpress( t_CKUINT channel, t_CKUINT pressure ); t_CKUINT pitchbend( t_CKUINT channel, t_CKUINT bend_val ); t_CKUINT allnotesoff( t_CKUINT channel ); public: RtMidiOut * mout; std::vector m_msg; t_CKUINT m_device_num; t_CKBOOL m_valid; t_CKBOOL m_suppress_output; }; //----------------------------------------------------------------------------- // name: class MidiIn // desc: midi //----------------------------------------------------------------------------- class MidiIn : public Chuck_Event { public: MidiIn(); ~MidiIn(); public: t_CKBOOL open( t_CKUINT device_num = 0 ); t_CKBOOL close(); t_CKBOOL good() { return m_valid; } t_CKINT num() { return m_valid ? (t_CKINT)m_device_num : -1; } public: void set_suppress( t_CKBOOL print_or_not ) { m_suppress_output = print_or_not; } t_CKBOOL get_suppress() { return m_suppress_output; } public: t_CKBOOL empty(); t_CKUINT recv( MidiMsg * msg ); public: CBufferAdvance * m_buffer; t_CKUINT m_read_index; RtMidiIn * min; t_CKBOOL m_valid; t_CKUINT m_device_num; Chuck_Object * SELF; t_CKBOOL m_suppress_output; }; void probeMidiIn(); void probeMidiOut(); class MidiInManager { public: static t_CKBOOL open( MidiIn * min, t_CKINT device_num ); static t_CKBOOL close( MidiIn * min ); static void cb_midi_input( double deltatime, std::vector * msg, void *userData ); protected: MidiInManager(); ~MidiInManager(); static std::vector the_mins; static std::vector the_bufs; }; class MidiOutManager { public: static t_CKBOOL open( MidiOut * mout, t_CKINT device_num ); static t_CKBOOL close( MidiOut * mout ); protected: MidiOutManager(); ~MidiOutManager(); static std::vector the_mouts; }; //----------------------------------------------------------------------------- // name: class MidiRW // desc: reads and writes midi messages from file //----------------------------------------------------------------------------- class MidiRW { public: MidiRW(); ~MidiRW(); public: t_CKBOOL open( const char * filename ); t_CKBOOL close(); public: t_CKBOOL read( MidiMsg * msg, t_CKTIME * time ); t_CKBOOL write( MidiMsg * msg, t_CKTIME * time ); protected: FILE * file; }; // closes all MidiRW file handles t_CKBOOL midirw_detach( ); //----------------------------------------------------------------------------- // name: class MidiMsgOut // desc: reads midi messages from file //----------------------------------------------------------------------------- class MidiMsgOut { public: MidiMsgOut(); ~MidiMsgOut(); public: t_CKBOOL open( const char * filename ); t_CKBOOL close(); public: t_CKBOOL write( MidiMsg * msg, t_CKTIME * time ); protected: FILE * file; }; //----------------------------------------------------------------------------- // name: class MidiMsgIn // desc: reads midi messages from file //----------------------------------------------------------------------------- class MidiMsgIn { public: MidiMsgIn(); ~MidiMsgIn(); public: t_CKBOOL open( const char * filename ); t_CKBOOL close(); public: t_CKBOOL read( MidiMsg * msg, t_CKTIME * time ); protected: FILE * file; }; #endif chuck-1.2.0.8.dfsg/src/rtaudio.cpp0000644000175000017500000111015110600421721015300 0ustar piempiem/************************************************************************/ /*! \class RtAudio \brief Realtime audio i/o C++ classes. RtAudio provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, Jack, and OSS), SGI, Macintosh OS X (CoreAudio), and Windows (DirectSound and ASIO) operating systems. RtAudio WWW site: http://music.mcgill.ca/~gary/rtaudio/ RtAudio: realtime audio i/o C++ classes Copyright (c) 2001-2005 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /************************************************************************/ // RtAudio: Version 3.0.2 (14 October 2005) // Modified by Robin Davies, 1 October 2005 // - Improvements to DirectX pointer chasing. // - Backdoor RtDsStatistics hook provides DirectX performance information. // - Bug fix for non-power-of-two Asio granularity used by Edirol PCR-A30. // - Auto-call CoInitialize for DSOUND and ASIO platforms. // chuck #include "rtaudio.h" #include "chuck_errmsg.h" #include "digiio_rtaudio.h" #include // old // #include "RtAudio.h" // #include // #include // Static variable definitions. const unsigned int RtApi::MAX_SAMPLE_RATES = 14; const unsigned int RtApi::SAMPLE_RATES[] = { 4000, 5512, 8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000 }; // chuck #if ( defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) ) && !defined(__WINDOWS_PTHREAD__) // old // #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) #define MUTEX_INITIALIZE(A) InitializeCriticalSection(A) #define MUTEX_DESTROY(A) DeleteCriticalSection(A); #define MUTEX_LOCK(A) EnterCriticalSection(A) #define MUTEX_UNLOCK(A) LeaveCriticalSection(A) #else // pthread API #define MUTEX_INITIALIZE(A) pthread_mutex_init(A, NULL) #define MUTEX_DESTROY(A) pthread_mutex_destroy(A); #define MUTEX_LOCK(A) pthread_mutex_lock(A) #define MUTEX_UNLOCK(A) pthread_mutex_unlock(A) #endif // *************************************************** // // // Public common (OS-independent) methods. // // *************************************************** // RtAudio :: RtAudio( RtAudioApi api ) { initialize( api ); } RtAudio :: RtAudio( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers, RtAudioApi api ) { initialize( api ); try { rtapi_->openStream( outputDevice, outputChannels, inputDevice, inputChannels, format, sampleRate, bufferSize, numberOfBuffers ); } catch (RtError &exception) { // Deallocate the RtApi instance. delete rtapi_; throw exception; } } RtAudio :: RtAudio( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers, RtAudioApi api ) { initialize( api ); try { rtapi_->openStream( outputDevice, outputChannels, inputDevice, inputChannels, format, sampleRate, bufferSize, numberOfBuffers ); } catch (RtError &exception) { // Deallocate the RtApi instance. delete rtapi_; throw exception; } } RtAudio :: ~RtAudio() { delete rtapi_; } void RtAudio :: openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers ) { rtapi_->openStream( outputDevice, outputChannels, inputDevice, inputChannels, format, sampleRate, bufferSize, numberOfBuffers ); } void RtAudio :: openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers ) { rtapi_->openStream( outputDevice, outputChannels, inputDevice, inputChannels, format, sampleRate, bufferSize, *numberOfBuffers ); } void RtAudio::initialize( RtAudioApi api ) { rtapi_ = 0; // First look for a compiled match to a specified API value. If one // of these constructors throws an error, it will be passed up the // inheritance chain. #if defined(__LINUX_JACK__) if ( api == LINUX_JACK ) rtapi_ = new RtApiJack(); #endif #if defined(__LINUX_ALSA__) if ( api == LINUX_ALSA ) rtapi_ = new RtApiAlsa(); #endif #if defined(__LINUX_OSS__) if ( api == LINUX_OSS ) rtapi_ = new RtApiOss(); #endif #if defined(__WINDOWS_ASIO__) if ( api == WINDOWS_ASIO ) rtapi_ = new RtApiAsio(); #endif #if defined(__WINDOWS_DS__) if ( api == WINDOWS_DS ) rtapi_ = new RtApiDs(); #endif #if defined(__IRIX_AL__) if ( api == IRIX_AL ) rtapi_ = new RtApiAl(); #endif #if defined(__MACOSX_CORE__) if ( api == MACOSX_CORE ) rtapi_ = new RtApiCore(); #endif if ( rtapi_ ) return; if ( api > 0 ) { // No compiled support for specified API value. throw RtError( "(via rtaudio): no compiled support for specified API!", RtError::INVALID_PARAMETER ); } // No specified API ... search for "best" option. try { #if defined(__LINUX_JACK__) rtapi_ = new RtApiJack(); #elif defined(__WINDOWS_ASIO__) rtapi_ = new RtApiAsio(); #elif defined(__IRIX_AL__) rtapi_ = new RtApiAl(); #elif defined(__MACOSX_CORE__) rtapi_ = new RtApiCore(); #else ; #endif } catch (RtError &) { #if defined(__RTAUDIO_DEBUG__) // chuck EM_log( CK_LOG_SYSTEM, "RtAudio: no devices found for first api option (JACK, ASIO, Al, or CoreAudio)..."); #endif rtapi_ = 0; } if ( rtapi_ ) return; // Try second API support if ( rtapi_ == 0 ) { try { #if defined(__LINUX_ALSA__) rtapi_ = new RtApiAlsa(); #elif defined(__WINDOWS_DS__) rtapi_ = new RtApiDs(); #else ; #endif } catch (RtError &) { #if defined(__RTAUDIO_DEBUG__) EM_log( CK_LOG_SYSTEM, "RtAudio: no devices found for second api option (Alsa or DirectSound)..."); #endif rtapi_ = 0; } } if ( rtapi_ ) return; // Try third API support if ( rtapi_ == 0 ) { #if defined(__LINUX_OSS__) try { rtapi_ = new RtApiOss(); } catch (RtError &error) { rtapi_ = 0; } #else ; #endif } if ( rtapi_ == 0 ) { // No devices found. throw RtError( "(via rtaudio): no devices found for compiled audio APIs!", RtError::NO_DEVICES_FOUND ); } } RtApi :: RtApi() { stream_.mode = UNINITIALIZED; stream_.state = STREAM_STOPPED; stream_.apiHandle = 0; MUTEX_INITIALIZE(&stream_.mutex); } RtApi :: ~RtApi() { MUTEX_DESTROY(&stream_.mutex); } void RtApi :: openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers ) { this->openStream( outputDevice, outputChannels, inputDevice, inputChannels, format, sampleRate, bufferSize, *numberOfBuffers ); *numberOfBuffers = stream_.nBuffers; } void RtApi :: openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers ) { if ( stream_.mode != UNINITIALIZED ) { sprintf(message_, "(via rtaudio): only one open stream allowed per class instance."); error(RtError::INVALID_STREAM); } if ( outputChannels < 1 && inputChannels < 1 ) { sprintf(message_,"(via rtaudio): one or both 'channel' parameters must be greater than zero."); error(RtError::INVALID_PARAMETER); } if ( formatBytes(format) == 0 ) { sprintf(message_,"(via rtaudio): 'format' parameter value is undefined."); error(RtError::INVALID_PARAMETER); } if ( outputChannels > 0 ) { if (outputDevice > nDevices_ || outputDevice < 0) { sprintf(message_,"(via rtaudio): 'outputDevice' parameter value (%d) is invalid.", outputDevice); error(RtError::INVALID_PARAMETER); } } if ( inputChannels > 0 ) { if (inputDevice > nDevices_ || inputDevice < 0) { sprintf(message_,"(via rtaudio): 'inputDevice' parameter value (%d) is invalid.", inputDevice); error(RtError::INVALID_PARAMETER); } } std::string errorMessages; clearStreamInfo(); bool result = FAILURE; int device, defaultDevice = 0; StreamMode mode; int channels; if ( outputChannels > 0 ) { mode = OUTPUT; channels = outputChannels; if ( outputDevice == 0 ) { // Try default device first. defaultDevice = getDefaultOutputDevice(); device = defaultDevice; } else device = outputDevice - 1; for ( int i=-1; i= 0 ) { if ( i == defaultDevice ) continue; device = i; } if ( devices_[device].probed == false ) { // If the device wasn't successfully probed before, try it // (again) now. clearDeviceInfo(&devices_[device]); probeDeviceInfo(&devices_[device]); } if ( devices_[device].probed ) result = probeDeviceOpen(device, mode, channels, sampleRate, format, bufferSize, numberOfBuffers); if ( result == SUCCESS ) break; errorMessages.append( "... " ); errorMessages.append( message_ ); errorMessages.append( "\n" ); if ( outputDevice > 0 ) break; clearStreamInfo(); } } if ( inputChannels > 0 && ( result == SUCCESS || outputChannels <= 0 ) ) { mode = INPUT; channels = inputChannels; if ( inputDevice == 0 ) { // Try default device first. defaultDevice = getDefaultInputDevice(); device = defaultDevice; } else device = inputDevice - 1; for ( int i=-1; i= 0 ) { if ( i == defaultDevice ) continue; device = i; } if ( devices_[device].probed == false ) { // If the device wasn't successfully probed before, try it // (again) now. clearDeviceInfo(&devices_[device]); probeDeviceInfo(&devices_[device]); } if ( devices_[device].probed ) result = probeDeviceOpen( device, mode, channels, sampleRate, format, bufferSize, numberOfBuffers ); if ( result == SUCCESS ) break; errorMessages.append( "... " ); errorMessages.append( message_ ); errorMessages.append( "\n" ); if ( inputDevice > 0 ) break; } } if ( result == SUCCESS ) return; // If we get here, all attempted probes failed. Close any opened // devices and clear the stream structure. if ( stream_.mode != UNINITIALIZED ) closeStream(); clearStreamInfo(); if ( ( outputDevice == 0 && outputChannels > 0 ) || ( inputDevice == 0 && inputChannels > 0 ) ) sprintf(message_,"(via rtaudio): no devices found for given stream parameters: \n%s", errorMessages.c_str()); else sprintf(message_,"(via rtaudio): unable to open specified device(s) with given stream parameters: \n%s", errorMessages.c_str()); error(RtError::INVALID_PARAMETER); return; } int RtApi :: getDeviceCount(void) { return devices_.size(); } RtApi::StreamState RtApi :: getStreamState( void ) const { return stream_.state; } RtAudioDeviceInfo RtApi :: getDeviceInfo( int device ) { if (device > (int) devices_.size() || device < 1) { sprintf(message_, "(via rtaudio): invalid device specifier (%d)...", device); error(RtError::INVALID_DEVICE); } RtAudioDeviceInfo info; int deviceIndex = device - 1; // If the device wasn't successfully probed before, try it now (or again). if (devices_[deviceIndex].probed == false) { clearDeviceInfo(&devices_[deviceIndex]); probeDeviceInfo(&devices_[deviceIndex]); } info.name.append( devices_[deviceIndex].name ); info.probed = devices_[deviceIndex].probed; if ( info.probed == true ) { info.outputChannels = devices_[deviceIndex].maxOutputChannels; info.inputChannels = devices_[deviceIndex].maxInputChannels; info.duplexChannels = devices_[deviceIndex].maxDuplexChannels; for (unsigned int i=0; i #include #include #include #include #include #include #include #include #define DAC_NAME "/dev/dsp" #define MAX_DEVICES 16 #define MAX_CHANNELS 16 extern "C" void *ossCallbackHandler(void * ptr); RtApiOss :: RtApiOss() { this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiOss: no Linux OSS audio devices found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiOss :: ~RtApiOss() { if ( stream_.mode != UNINITIALIZED ) closeStream(); } void RtApiOss :: initialize(void) { // Count cards and devices nDevices_ = 0; // We check /dev/dsp before probing devices. /dev/dsp is supposed to // be a link to the "default" audio device, of the form /dev/dsp0, // /dev/dsp1, etc... However, I've seen many cases where /dev/dsp was a // real device, so we need to check for that. Also, sometimes the // link is to /dev/dspx and other times just dspx. I'm not sure how // the latter works, but it does. char device_name[16]; struct stat dspstat; int dsplink = -1; int i = 0; if (lstat(DAC_NAME, &dspstat) == 0) { if (S_ISLNK(dspstat.st_mode)) { i = readlink(DAC_NAME, device_name, sizeof(device_name)); if (i > 0) { device_name[i] = '\0'; if (i > 8) { // check for "/dev/dspx" if (!strncmp(DAC_NAME, device_name, 8)) dsplink = atoi(&device_name[8]); } else if (i > 3) { // check for "dspx" if (!strncmp("dsp", device_name, 3)) dsplink = atoi(&device_name[3]); } } else { sprintf(message_, "RtApiOss: cannot read value of symbolic link %s.", DAC_NAME); error(RtError::SYSTEM_ERROR); } } } else { sprintf(message_, "RtApiOss: cannot stat %s.", DAC_NAME); error(RtError::SYSTEM_ERROR); } // The OSS API doesn't provide a routine for determining the number // of devices. Thus, we'll just pursue a brute force method. The // idea is to start with /dev/dsp(0) and continue with higher device // numbers until we reach MAX_DSP_DEVICES. This should tell us how // many devices we have ... it is not a fullproof scheme, but hopefully // it will work most of the time. int fd = 0; RtApiDevice device; for (i=-1; i= 0) close(fd); device.name.erase(); device.name.append( (const char *)device_name, strlen(device_name)+1); devices_.push_back(device); nDevices_++; } } void RtApiOss :: probeDeviceInfo(RtApiDevice *info) { int i, fd, channels, mask; // The OSS API doesn't provide a means for probing the capabilities // of devices. Thus, we'll just pursue a brute force method. // First try for playback fd = open(info->name.c_str(), O_WRONLY | O_NONBLOCK); if (fd == -1) { // Open device failed ... either busy or doesn't exist if (errno == EBUSY || errno == EAGAIN) sprintf(message_, "RtApiOss: OSS playback device (%s) is busy and cannot be probed.", info->name.c_str()); else sprintf(message_, "RtApiOss: OSS playback device (%s) open error.", info->name.c_str()); error(RtError::DEBUG_WARNING); goto capture_probe; } // We have an open device ... see how many channels it can handle for (i=MAX_CHANNELS; i>0; i--) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1) { // This would normally indicate some sort of hardware error, but under ALSA's // OSS emulation, it sometimes indicates an invalid channel value. Further, // the returned channel value is not changed. So, we'll ignore the possible // hardware error. continue; // try next channel number } // Check to see whether the device supports the requested number of channels if (channels != i ) continue; // try next channel number // If here, we found the largest working channel value break; } info->maxOutputChannels = i; // Now find the minimum number of channels it can handle for (i=1; i<=info->maxOutputChannels; i++) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) continue; // try next channel number // If here, we found the smallest working channel value break; } info->minOutputChannels = i; close(fd); capture_probe: // Now try for capture fd = open(info->name.c_str(), O_RDONLY | O_NONBLOCK); if (fd == -1) { // Open device for capture failed ... either busy or doesn't exist if (errno == EBUSY || errno == EAGAIN) sprintf(message_, "RtApiOss: OSS capture device (%s) is busy and cannot be probed.", info->name.c_str()); else sprintf(message_, "RtApiOss: OSS capture device (%s) open error.", info->name.c_str()); error(RtError::DEBUG_WARNING); if (info->maxOutputChannels == 0) // didn't open for playback either ... device invalid return; goto probe_parameters; } // We have the device open for capture ... see how many channels it can handle for (i=MAX_CHANNELS; i>0; i--) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) { continue; // as above } // If here, we found a working channel value break; } info->maxInputChannels = i; // Now find the minimum number of channels it can handle for (i=1; i<=info->maxInputChannels; i++) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) continue; // try next channel number // If here, we found the smallest working channel value break; } info->minInputChannels = i; close(fd); if (info->maxOutputChannels == 0 && info->maxInputChannels == 0) { sprintf(message_, "RtApiOss: device (%s) reports zero channels for input and output.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // If device opens for both playback and capture, we determine the channels. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0) goto probe_parameters; fd = open(info->name.c_str(), O_RDWR | O_NONBLOCK); if (fd == -1) goto probe_parameters; ioctl(fd, SNDCTL_DSP_SETDUPLEX, 0); ioctl(fd, SNDCTL_DSP_GETCAPS, &mask); if (mask & DSP_CAP_DUPLEX) { info->hasDuplexSupport = true; // We have the device open for duplex ... see how many channels it can handle for (i=MAX_CHANNELS; i>0; i--) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) continue; // as above // If here, we found a working channel value break; } info->maxDuplexChannels = i; // Now find the minimum number of channels it can handle for (i=1; i<=info->maxDuplexChannels; i++) { channels = i; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) continue; // try next channel number // If here, we found the smallest working channel value break; } info->minDuplexChannels = i; } close(fd); probe_parameters: // At this point, we need to figure out the supported data formats // and sample rates. We'll proceed by openning the device in the // direction with the maximum number of channels, or playback if // they are equal. This might limit our sample rate options, but so // be it. if (info->maxOutputChannels >= info->maxInputChannels) { fd = open(info->name.c_str(), O_WRONLY | O_NONBLOCK); channels = info->maxOutputChannels; } else { fd = open(info->name.c_str(), O_RDONLY | O_NONBLOCK); channels = info->maxInputChannels; } if (fd == -1) { // We've got some sort of conflict ... abort sprintf(message_, "RtApiOss: device (%s) won't reopen during probe.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // We have an open device ... set to maximum channels. i = channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &channels) == -1 || channels != i) { // We've got some sort of conflict ... abort close(fd); sprintf(message_, "RtApiOss: device (%s) won't revert to previous channel setting.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) { close(fd); sprintf(message_, "RtApiOss: device (%s) can't get supported audio formats.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Probe the supported data formats ... we don't care about endian-ness just yet. int format; info->nativeFormats = 0; #if defined (AFMT_S32_BE) // This format does not seem to be in the 2.4 kernel version of OSS soundcard.h if (mask & AFMT_S32_BE) { format = AFMT_S32_BE; info->nativeFormats |= RTAUDIO_SINT32; } #endif #if defined (AFMT_S32_LE) /* This format is not in the 2.4.4 kernel version of OSS soundcard.h */ if (mask & AFMT_S32_LE) { format = AFMT_S32_LE; info->nativeFormats |= RTAUDIO_SINT32; } #endif if (mask & AFMT_S8) { format = AFMT_S8; info->nativeFormats |= RTAUDIO_SINT8; } if (mask & AFMT_S16_BE) { format = AFMT_S16_BE; info->nativeFormats |= RTAUDIO_SINT16; } if (mask & AFMT_S16_LE) { format = AFMT_S16_LE; info->nativeFormats |= RTAUDIO_SINT16; } // Check that we have at least one supported format if (info->nativeFormats == 0) { close(fd); sprintf(message_, "RtApiOss: device (%s) data format not supported by RtAudio.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Set the format i = format; if (ioctl(fd, SNDCTL_DSP_SETFMT, &format) == -1 || format != i) { close(fd); sprintf(message_, "RtApiOss: device (%s) error setting data format.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Probe the supported sample rates. info->sampleRates.clear(); for (unsigned int k=0; ksampleRates.push_back(speed); } if (info->sampleRates.size() == 0) { close(fd); sprintf(message_, "RtApiOss: no supported sample rates found for device (%s).", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // That's all ... close the device and return close(fd); info->probed = true; return; } bool RtApiOss :: probeDeviceOpen(int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers) { int buffers, buffer_bytes, device_channels, device_format; int srate, temp, fd; int *handle = (int *) stream_.apiHandle; const char *name = devices_[device].name.c_str(); if (mode == OUTPUT) fd = open(name, O_WRONLY | O_NONBLOCK); else { // mode == INPUT if (stream_.mode == OUTPUT && stream_.device[0] == device) { // We just set the same device for playback ... close and reopen for duplex (OSS only). close(handle[0]); handle[0] = 0; // First check that the number previously set channels is the same. if (stream_.nUserChannels[0] != channels) { sprintf(message_, "RtApiOss: input/output channels must be equal for OSS duplex device (%s).", name); goto error; } fd = open(name, O_RDWR | O_NONBLOCK); } else fd = open(name, O_RDONLY | O_NONBLOCK); } if (fd == -1) { if (errno == EBUSY || errno == EAGAIN) sprintf(message_, "RtApiOss: device (%s) is busy and cannot be opened.", name); else sprintf(message_, "RtApiOss: device (%s) cannot be opened.", name); goto error; } // Now reopen in blocking mode. close(fd); if (mode == OUTPUT) fd = open(name, O_WRONLY | O_SYNC); else { // mode == INPUT if (stream_.mode == OUTPUT && stream_.device[0] == device) fd = open(name, O_RDWR | O_SYNC); else fd = open(name, O_RDONLY | O_SYNC); } if (fd == -1) { sprintf(message_, "RtApiOss: device (%s) cannot be opened.", name); goto error; } // Get the sample format mask int mask; if (ioctl(fd, SNDCTL_DSP_GETFMTS, &mask) == -1) { close(fd); sprintf(message_, "RtApiOss: device (%s) can't get supported audio formats.", name); goto error; } // Determine how to set the device format. stream_.userFormat = format; device_format = -1; stream_.doByteSwap[mode] = false; if (format == RTAUDIO_SINT8) { if (mask & AFMT_S8) { device_format = AFMT_S8; stream_.deviceFormat[mode] = RTAUDIO_SINT8; } } else if (format == RTAUDIO_SINT16) { if (mask & AFMT_S16_NE) { device_format = AFMT_S16_NE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; } #if BYTE_ORDER == LITTLE_ENDIAN else if (mask & AFMT_S16_BE) { device_format = AFMT_S16_BE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; stream_.doByteSwap[mode] = true; } #else else if (mask & AFMT_S16_LE) { device_format = AFMT_S16_LE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; stream_.doByteSwap[mode] = true; } #endif } #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE) else if (format == RTAUDIO_SINT32) { if (mask & AFMT_S32_NE) { device_format = AFMT_S32_NE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; } #if BYTE_ORDER == LITTLE_ENDIAN else if (mask & AFMT_S32_BE) { device_format = AFMT_S32_BE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; stream_.doByteSwap[mode] = true; } #else else if (mask & AFMT_S32_LE) { device_format = AFMT_S32_LE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; stream_.doByteSwap[mode] = true; } #endif } #endif if (device_format == -1) { // The user requested format is not natively supported by the device. if (mask & AFMT_S16_NE) { device_format = AFMT_S16_NE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; } #if BYTE_ORDER == LITTLE_ENDIAN else if (mask & AFMT_S16_BE) { device_format = AFMT_S16_BE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; stream_.doByteSwap[mode] = true; } #else else if (mask & AFMT_S16_LE) { device_format = AFMT_S16_LE; stream_.deviceFormat[mode] = RTAUDIO_SINT16; stream_.doByteSwap[mode] = true; } #endif #if defined (AFMT_S32_NE) && defined (AFMT_S32_LE) && defined (AFMT_S32_BE) else if (mask & AFMT_S32_NE) { device_format = AFMT_S32_NE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; } #if BYTE_ORDER == LITTLE_ENDIAN else if (mask & AFMT_S32_BE) { device_format = AFMT_S32_BE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; stream_.doByteSwap[mode] = true; } #else else if (mask & AFMT_S32_LE) { device_format = AFMT_S32_LE; stream_.deviceFormat[mode] = RTAUDIO_SINT32; stream_.doByteSwap[mode] = true; } #endif #endif else if (mask & AFMT_S8) { device_format = AFMT_S8; stream_.deviceFormat[mode] = RTAUDIO_SINT8; } } if (stream_.deviceFormat[mode] == 0) { // This really shouldn't happen ... close(fd); sprintf(message_, "RtApiOss: device (%s) data format not supported by RtAudio.", name); goto error; } // Determine the number of channels for this device. Note that the // channel value requested by the user might be < min_X_Channels. stream_.nUserChannels[mode] = channels; device_channels = channels; if (mode == OUTPUT) { if (channels < devices_[device].minOutputChannels) device_channels = devices_[device].minOutputChannels; } else { // mode == INPUT if (stream_.mode == OUTPUT && stream_.device[0] == device) { // We're doing duplex setup here. if (channels < devices_[device].minDuplexChannels) device_channels = devices_[device].minDuplexChannels; } else { if (channels < devices_[device].minInputChannels) device_channels = devices_[device].minInputChannels; } } stream_.nDeviceChannels[mode] = device_channels; // Attempt to set the buffer size. According to OSS, the minimum // number of buffers is two. The supposed minimum buffer size is 16 // bytes, so that will be our lower bound. The argument to this // call is in the form 0xMMMMSSSS (hex), where the buffer size (in // bytes) is given as 2^SSSS and the number of buffers as 2^MMMM. // We'll check the actual value used near the end of the setup // procedure. buffer_bytes = *bufferSize * formatBytes(stream_.deviceFormat[mode]) * device_channels; if (buffer_bytes < 16) buffer_bytes = 16; buffers = numberOfBuffers; if (buffers < 2) buffers = 2; temp = ((int) buffers << 16) + (int)(log10((double)buffer_bytes)/log10(2.0)); if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &temp)) { close(fd); sprintf(message_, "RtApiOss: error setting fragment size for device (%s).", name); goto error; } stream_.nBuffers = buffers; // Set the data format. temp = device_format; if (ioctl(fd, SNDCTL_DSP_SETFMT, &device_format) == -1 || device_format != temp) { close(fd); sprintf(message_, "RtApiOss: error setting data format for device (%s).", name); goto error; } // Set the number of channels. temp = device_channels; if (ioctl(fd, SNDCTL_DSP_CHANNELS, &device_channels) == -1 || device_channels != temp) { close(fd); sprintf(message_, "RtApiOss: error setting %d channels on device (%s).", temp, name); goto error; } // Set the sample rate. srate = sampleRate; temp = srate; if (ioctl(fd, SNDCTL_DSP_SPEED, &srate) == -1) { close(fd); sprintf(message_, "RtApiOss: error setting sample rate = %d on device (%s).", temp, name); goto error; } // Verify the sample rate setup worked. if (abs(srate - temp) > 100) { close(fd); sprintf(message_, "RtApiOss: error ... audio device (%s) doesn't support sample rate of %d.", name, temp); goto error; } stream_.sampleRate = sampleRate; if (ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &buffer_bytes) == -1) { close(fd); sprintf(message_, "RtApiOss: error getting buffer size for device (%s).", name); goto error; } // Save buffer size (in sample frames). *bufferSize = buffer_bytes / (formatBytes(stream_.deviceFormat[mode]) * device_channels); stream_.bufferSize = *bufferSize; if (mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] == device) { // We're doing duplex setup here. stream_.deviceFormat[0] = stream_.deviceFormat[1]; stream_.nDeviceChannels[0] = device_channels; } // Allocate the stream handles if necessary and then save. if ( stream_.apiHandle == 0 ) { handle = (int *) calloc(2, sizeof(int)); stream_.apiHandle = (void *) handle; handle[0] = 0; handle[1] = 0; } else { handle = (int *) stream_.apiHandle; } handle[mode] = fd; // Set flags for buffer conversion stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode]) stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { close(fd); sprintf(message_, "RtApiOss: error allocating user buffer memory (%s).", name); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { close(fd); sprintf(message_, "RtApiOss: error allocating device buffer memory (%s).", name); goto error; } } } stream_.device[mode] = device; stream_.state = STREAM_STOPPED; if ( stream_.mode == OUTPUT && mode == INPUT ) { stream_.mode = DUPLEX; if (stream_.device[0] == device) handle[0] = fd; } else stream_.mode = mode; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; kstopStream(); } void RtApiOss :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; if ( info->usingCallback ) { sprintf(message_, "RtApiOss: A callback is already set for this stream!"); error(RtError::WARNING); return; } info->callback = (void *) callback; info->userData = userData; info->usingCallback = true; info->object = (void *) this; // Set the thread attributes for joinable and realtime scheduling // priority. The higher priority will only take affect if the // program is run as root or suid. pthread_attr_t attr; pthread_attr_init(&attr); // chuck (commented out) // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // pthread_attr_setschedpolicy(&attr, SCHED_RR); int err = pthread_create(&(info->thread), &attr, ossCallbackHandler, &stream_.callbackInfo); pthread_attr_destroy(&attr); if (err) { info->usingCallback = false; sprintf(message_, "RtApiOss: error starting callback thread!"); error(RtError::THREAD_ERROR); } } void RtApiOss :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; pthread_join(stream_.callbackInfo.thread, NULL); stream_.callbackInfo.thread = 0; stream_.callbackInfo.callback = NULL; stream_.callbackInfo.userData = NULL; MUTEX_UNLOCK(&stream_.mutex); } } extern "C" void *ossCallbackHandler(void *ptr) { CallbackInfo *info = (CallbackInfo *) ptr; RtApiOss *object = (RtApiOss *) info->object; bool *usingCallback = &info->usingCallback; while ( *usingCallback ) { pthread_testcancel(); try { object->tickStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiOss: callback thread error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_log( CK_LOG_INFO, "closing thread..." ); EM_poplog(); break; } } return 0; } //******************** End of __LINUX_OSS__ *********************// #endif #if defined(__MACOSX_CORE__) // The OS X CoreAudio API is designed to use a separate callback // procedure for each of its audio devices. A single RtAudio duplex // stream using two different devices is supported here, though it // cannot be guaranteed to always behave correctly because we cannot // synchronize these two callbacks. This same functionality can be // achieved with better synchrony by opening two separate streams for // the devices and using RtAudio blocking calls (i.e. tickStream()). // // A property listener is installed for over/underrun information. // However, no functionality is currently provided to allow property // listeners to trigger user handlers because it is unclear what could // be done if a critical stream parameter (buffer size, sample rate, // device disconnect) notification arrived. The listeners entail // quite a bit of extra code and most likely, a user program wouldn't // be prepared for the result anyway. // A structure to hold various information related to the CoreAudio API // implementation. struct CoreHandle { UInt32 index[2]; bool stopStream; bool xrun; char *deviceBuffer; pthread_cond_t condition; CoreHandle() :stopStream(false), xrun(false), deviceBuffer(0) {} }; RtApiCore :: RtApiCore() { this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiCore: no Macintosh OS-X Core Audio devices found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiCore :: ~RtApiCore() { // The subclass destructor gets called before the base class // destructor, so close an existing stream before deallocating // apiDeviceId memory. if ( stream_.mode != UNINITIALIZED ) closeStream(); // Free our allocated apiDeviceId memory. AudioDeviceID *id; for ( unsigned int i=0; iapiDeviceId; err = AudioDeviceGetProperty( *id, 0, false, kAudioDevicePropertyDeviceManufacturer, &dataSize, name ); if (err != noErr) { sprintf( message_, "RtApiCore: OS-X error getting device manufacturer." ); error(RtError::DEBUG_WARNING); return; } strncpy(fullname, name, 256); strcat(fullname, ": " ); dataSize = 256; err = AudioDeviceGetProperty( *id, 0, false, kAudioDevicePropertyDeviceName, &dataSize, name ); if (err != noErr) { sprintf( message_, "RtApiCore: OS-X error getting device name." ); error(RtError::DEBUG_WARNING); return; } strncat(fullname, name, 254); info->name.erase(); info->name.append( (const char *)fullname, strlen(fullname)+1); // Get output channel information. unsigned int i, minChannels = 0, maxChannels = 0, nStreams = 0; AudioBufferList *bufferList = nil; err = AudioDeviceGetPropertyInfo( *id, 0, false, kAudioDevicePropertyStreamConfiguration, &dataSize, NULL ); if (err == noErr && dataSize > 0) { bufferList = (AudioBufferList *) malloc( dataSize ); if (bufferList == NULL) { sprintf(message_, "RtApiCore: memory allocation error!"); error(RtError::DEBUG_WARNING); return; } err = AudioDeviceGetProperty( *id, 0, false, kAudioDevicePropertyStreamConfiguration, &dataSize, bufferList ); if (err == noErr) { maxChannels = 0; minChannels = 1000; nStreams = bufferList->mNumberBuffers; for ( i=0; imBuffers[i].mNumberChannels; if ( bufferList->mBuffers[i].mNumberChannels < minChannels ) minChannels = bufferList->mBuffers[i].mNumberChannels; } } } free (bufferList); if (err != noErr || dataSize <= 0) { sprintf( message_, "RtApiCore: OS-X error getting output channels for device (%s).", info->name.c_str() ); error(RtError::DEBUG_WARNING); return; } if ( nStreams ) { if ( maxChannels > 0 ) info->maxOutputChannels = maxChannels; if ( minChannels > 0 ) info->minOutputChannels = minChannels; } // Get input channel information. bufferList = nil; err = AudioDeviceGetPropertyInfo( *id, 0, true, kAudioDevicePropertyStreamConfiguration, &dataSize, NULL ); if (err == noErr && dataSize > 0) { bufferList = (AudioBufferList *) malloc( dataSize ); if (bufferList == NULL) { sprintf(message_, "RtApiCore: memory allocation error!"); error(RtError::DEBUG_WARNING); return; } err = AudioDeviceGetProperty( *id, 0, true, kAudioDevicePropertyStreamConfiguration, &dataSize, bufferList ); if (err == noErr) { maxChannels = 0; minChannels = 1000; nStreams = bufferList->mNumberBuffers; for ( i=0; imBuffers[i].mNumberChannels < minChannels ) minChannels = bufferList->mBuffers[i].mNumberChannels; maxChannels += bufferList->mBuffers[i].mNumberChannels; } } } free (bufferList); if (err != noErr || dataSize <= 0) { sprintf( message_, "RtApiCore: OS-X error getting input channels for device (%s).", info->name.c_str() ); error(RtError::DEBUG_WARNING); return; } if ( nStreams ) { if ( maxChannels > 0 ) info->maxInputChannels = maxChannels; if ( minChannels > 0 ) info->minInputChannels = minChannels; } // If device opens for both playback and capture, we determine the channels. if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) { info->hasDuplexSupport = true; info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ? info->maxInputChannels : info->maxOutputChannels; info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ? info->minInputChannels : info->minOutputChannels; } // Probe the device sample rate and data format parameters. The // core audio query mechanism is performed on a "stream" // description, which can have a variable number of channels and // apply to input or output only. // Create a stream description structure. AudioStreamBasicDescription description; dataSize = sizeof( AudioStreamBasicDescription ); memset(&description, 0, sizeof(AudioStreamBasicDescription)); bool isInput = false; if ( info->maxOutputChannels == 0 ) isInput = true; bool isDuplex = false; if ( info->maxDuplexChannels > 0 ) isDuplex = true; // Determine the supported sample rates. info->sampleRates.clear(); for (unsigned int k=0; ksampleRates.push_back( SAMPLE_RATES[k] ); } if (info->sampleRates.size() == 0) { sprintf( message_, "RtApiCore: No supported sample rates found for OS-X device (%s).", info->name.c_str() ); error(RtError::DEBUG_WARNING); return; } // Determine the supported data formats. info->nativeFormats = 0; description.mFormatID = kAudioFormatLinearPCM; description.mBitsPerChannel = 8; description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT8; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT8; } description.mBitsPerChannel = 16; description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT16; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT16; } description.mBitsPerChannel = 32; description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT32; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT32; } description.mBitsPerChannel = 24; description.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsAlignedHigh | kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT24; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_SINT24; } description.mBitsPerChannel = 32; description.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_FLOAT32; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_FLOAT32; } description.mBitsPerChannel = 64; description.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_FLOAT64; else { description.mFormatFlags &= ~kLinearPCMFormatFlagIsBigEndian; if ( deviceSupportsFormat( *id, isInput, &description, isDuplex ) ) info->nativeFormats |= RTAUDIO_FLOAT64; } // Check that we have at least one supported format. if (info->nativeFormats == 0) { sprintf(message_, "RtApiCore: OS-X device (%s) data format not supported by RtAudio.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } info->probed = true; } OSStatus callbackHandler( AudioDeviceID inDevice, const AudioTimeStamp* inNow, const AudioBufferList* inInputData, const AudioTimeStamp* inInputTime, AudioBufferList* outOutputData, const AudioTimeStamp* inOutputTime, void* infoPointer ) { CallbackInfo *info = (CallbackInfo *) infoPointer; RtApiCore *object = (RtApiCore *) info->object; try { object->callbackEvent( inDevice, (void *)inInputData, (void *)outOutputData ); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiCore: callback handler error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_poplog(); return kAudioHardwareUnspecifiedError; } return kAudioHardwareNoError; } OSStatus deviceListener( AudioDeviceID inDevice, UInt32 channel, Boolean isInput, AudioDevicePropertyID propertyID, void* handlePointer ) { CoreHandle *handle = (CoreHandle *) handlePointer; if ( propertyID == kAudioDeviceProcessorOverload ) { if ( isInput ) // chuck log EM_log( CK_LOG_FINEST, "(via rtaudio): OS-X audio input overrun detected!" ); else // chuck log EM_log( CK_LOG_FINEST, "(via rtaudio): OS-X audio output overrun detected!" ); // chuck notify Digitalio::m_xrun += 2; handle->xrun = true; } return kAudioHardwareNoError; } bool RtApiCore :: probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ) { // Setup for stream mode. bool isInput = false; AudioDeviceID id = *((AudioDeviceID *) devices_[device].apiDeviceId); if ( mode == INPUT ) isInput = true; // Search for a stream which contains the desired number of channels. OSStatus err = noErr; UInt32 dataSize; unsigned int deviceChannels, nStreams = 0; UInt32 iChannel = 0, iStream = 0; AudioBufferList *bufferList = nil; err = AudioDeviceGetPropertyInfo( id, 0, isInput, kAudioDevicePropertyStreamConfiguration, &dataSize, NULL ); if (err == noErr && dataSize > 0) { bufferList = (AudioBufferList *) malloc( dataSize ); if (bufferList == NULL) { sprintf(message_, "RtApiCore: memory allocation error in probeDeviceOpen()!"); error(RtError::DEBUG_WARNING); return FAILURE; } err = AudioDeviceGetProperty( id, 0, isInput, kAudioDevicePropertyStreamConfiguration, &dataSize, bufferList ); if (err == noErr) { stream_.deInterleave[mode] = false; nStreams = bufferList->mNumberBuffers; for ( iStream=0; iStreammBuffers[iStream].mNumberChannels >= (unsigned int) channels ) break; iChannel += bufferList->mBuffers[iStream].mNumberChannels; } // If we didn't find a single stream above, see if we can meet // the channel specification in mono mode (i.e. using separate // non-interleaved buffers). This can only work if there are N // consecutive one-channel streams, where N is the number of // desired channels. iChannel = 0; if ( iStream >= nStreams && nStreams >= (unsigned int) channels ) { int counter = 0; for ( iStream=0; iStreammBuffers[iStream].mNumberChannels == 1 ) counter++; else counter = 0; if ( counter == channels ) { iStream -= channels - 1; iChannel -= channels - 1; stream_.deInterleave[mode] = true; break; } iChannel += bufferList->mBuffers[iStream].mNumberChannels; } } } } if (err != noErr || dataSize <= 0) { if ( bufferList ) free( bufferList ); sprintf( message_, "RtApiCore: OS-X error getting channels for device (%s).", devices_[device].name.c_str() ); error(RtError::DEBUG_WARNING); return FAILURE; } if (iStream >= nStreams) { free (bufferList); sprintf( message_, "RtApiCore: unable to find OS-X audio stream on device (%s) for requested channels (%d).", devices_[device].name.c_str(), channels ); error(RtError::DEBUG_WARNING); return FAILURE; } // This is ok even for mono mode ... it gets updated later. deviceChannels = bufferList->mBuffers[iStream].mNumberChannels; free (bufferList); // Determine the buffer size. AudioValueRange bufferRange; dataSize = sizeof(AudioValueRange); err = AudioDeviceGetProperty( id, 0, isInput, kAudioDevicePropertyBufferSizeRange, &dataSize, &bufferRange); if (err != noErr) { sprintf( message_, "RtApiCore: OS-X error getting buffer size range for device (%s).", devices_[device].name.c_str() ); error(RtError::DEBUG_WARNING); return FAILURE; } long bufferBytes = *bufferSize * deviceChannels * formatBytes(RTAUDIO_FLOAT32); if (bufferRange.mMinimum > bufferBytes) bufferBytes = (int) bufferRange.mMinimum; else if (bufferRange.mMaximum < bufferBytes) bufferBytes = (int) bufferRange.mMaximum; // Set the buffer size. For mono mode, I'm assuming we only need to // make this setting for the first channel. UInt32 theSize = (UInt32) bufferBytes; dataSize = sizeof( UInt32); err = AudioDeviceSetProperty(id, NULL, 0, isInput, kAudioDevicePropertyBufferSize, dataSize, &theSize); if (err != noErr) { sprintf( message_, "RtApiCore: OS-X error setting the buffer size for device (%s).", devices_[device].name.c_str() ); error(RtError::DEBUG_WARNING); return FAILURE; } // If attempting to setup a duplex stream, the bufferSize parameter // MUST be the same in both directions! *bufferSize = bufferBytes / ( deviceChannels * formatBytes(RTAUDIO_FLOAT32) ); if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { sprintf( message_, "RtApiCore: OS-X error setting buffer size for duplex stream on device (%s).", devices_[device].name.c_str() ); error(RtError::DEBUG_WARNING); return FAILURE; } stream_.bufferSize = *bufferSize; stream_.nBuffers = 1; // Set the stream format description. Do for each channel in mono mode. AudioStreamBasicDescription description; dataSize = sizeof( AudioStreamBasicDescription ); if ( stream_.deInterleave[mode] ) nStreams = channels; else nStreams = 1; for ( unsigned int i=0; i 1 && stream_.deInterleave[mode]) stream_.doConvertBuffer[mode] = true; // Allocate our CoreHandle structure for the stream. CoreHandle *handle; if ( stream_.apiHandle == 0 ) { handle = (CoreHandle *) calloc(1, sizeof(CoreHandle)); if ( handle == NULL ) { sprintf(message_, "RtApiCore: OS-X error allocating coreHandle memory (%s).", devices_[device].name.c_str()); goto error; } handle->index[0] = 0; handle->index[1] = 0; if ( pthread_cond_init(&handle->condition, NULL) ) { sprintf(message_, "RtApiCore: error initializing pthread condition variable (%s).", devices_[device].name.c_str()); goto error; } stream_.apiHandle = (void *) handle; } else handle = (CoreHandle *) stream_.apiHandle; handle->index[mode] = iStream; // Allocate necessary internal buffers. if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { sprintf(message_, "RtApiCore: OS-X error allocating user buffer memory (%s).", devices_[device].name.c_str()); goto error; } } if ( stream_.deInterleave[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiCore: error allocating device buffer memory (%s).", devices_[device].name.c_str()); goto error; } // If not de-interleaving, we point stream_.deviceBuffer to the // OS X supplied device buffer before doing any necessary data // conversions. This presents a problem if we have a duplex // stream using one device which needs de-interleaving and // another device which doesn't. So, save a pointer to our own // device buffer in the CallbackInfo structure. handle->deviceBuffer = stream_.deviceBuffer; } } stream_.sampleRate = sampleRate; stream_.device[mode] = device; stream_.state = STREAM_STOPPED; stream_.callbackInfo.object = (void *) this; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; kcondition); free(handle); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } error(RtError::DEBUG_WARNING); return FAILURE; } void RtApiCore :: closeStream() { // We don't want an exception to be thrown here because this // function is called by our class destructor. So, do our own // stream check. if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtApiCore::closeStream(): no open stream to close!"); error(RtError::WARNING); return; } AudioDeviceID id = *( (AudioDeviceID *) devices_[stream_.device[0]].apiDeviceId ); if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { if (stream_.state == STREAM_RUNNING) AudioDeviceStop( id, callbackHandler ); AudioDeviceRemoveIOProc( id, callbackHandler ); } id = *( (AudioDeviceID *) devices_[stream_.device[1]].apiDeviceId ); if (stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1]) ) { if (stream_.state == STREAM_RUNNING) AudioDeviceStop( id, callbackHandler ); AudioDeviceRemoveIOProc( id, callbackHandler ); } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } if ( stream_.deInterleave[0] || stream_.deInterleave[1] ) { free(stream_.deviceBuffer); stream_.deviceBuffer = 0; } CoreHandle *handle = (CoreHandle *) stream_.apiHandle; // Destroy pthread condition variable and free the CoreHandle structure. if ( handle ) { pthread_cond_destroy(&handle->condition); free( handle ); stream_.apiHandle = 0; } stream_.mode = UNINITIALIZED; } void RtApiCore :: startStream() { verifyStream(); if (stream_.state == STREAM_RUNNING) return; MUTEX_LOCK(&stream_.mutex); OSStatus err; AudioDeviceID id; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { id = *( (AudioDeviceID *) devices_[stream_.device[0]].apiDeviceId ); err = AudioDeviceStart(id, callbackHandler); if (err != noErr) { sprintf(message_, "RtApiCore: OS-X error starting callback procedure on device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } if (stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1]) ) { id = *( (AudioDeviceID *) devices_[stream_.device[1]].apiDeviceId ); err = AudioDeviceStart(id, callbackHandler); if (err != noErr) { sprintf(message_, "RtApiCore: OS-X error starting input callback procedure on device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } CoreHandle *handle = (CoreHandle *) stream_.apiHandle; handle->stopStream = false; stream_.state = STREAM_RUNNING; MUTEX_UNLOCK(&stream_.mutex); } void RtApiCore :: stopStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); OSStatus err; AudioDeviceID id; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { id = *( (AudioDeviceID *) devices_[stream_.device[0]].apiDeviceId ); err = AudioDeviceStop(id, callbackHandler); if (err != noErr) { sprintf(message_, "RtApiCore: OS-X error stopping callback procedure on device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } if (stream_.mode == INPUT || ( stream_.mode == DUPLEX && stream_.device[0] != stream_.device[1]) ) { id = *( (AudioDeviceID *) devices_[stream_.device[1]].apiDeviceId ); err = AudioDeviceStop(id, callbackHandler); if (err != noErr) { sprintf(message_, "RtApiCore: OS-X error stopping input callback procedure on device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } MUTEX_UNLOCK(&stream_.mutex); } void RtApiCore :: abortStream() { stopStream(); } void RtApiCore :: tickStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; if (stream_.callbackInfo.usingCallback) { sprintf(message_, "RtApiCore: tickStream() should not be used when a callback function is set!"); error(RtError::WARNING); return; } CoreHandle *handle = (CoreHandle *) stream_.apiHandle; MUTEX_LOCK(&stream_.mutex); pthread_cond_wait(&handle->condition, &stream_.mutex); MUTEX_UNLOCK(&stream_.mutex); } void RtApiCore :: callbackEvent( AudioDeviceID deviceId, void *inData, void *outData ) { verifyStream(); if (stream_.state == STREAM_STOPPED) return; CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; CoreHandle *handle = (CoreHandle *) stream_.apiHandle; AudioBufferList *inBufferList = (AudioBufferList *) inData; AudioBufferList *outBufferList = (AudioBufferList *) outData; if ( info->usingCallback && handle->stopStream ) { // Check if the stream should be stopped (via the previous user // callback return value). We stop the stream here, rather than // after the function call, so that output data can first be // processed. this->stopStream(); return; } MUTEX_LOCK(&stream_.mutex); // Invoke user callback first, to get fresh output data. Don't // invoke the user callback if duplex mode AND the input/output devices // are different AND this function is called for the input device. AudioDeviceID id = *( (AudioDeviceID *) devices_[stream_.device[0]].apiDeviceId ); if ( info->usingCallback && (stream_.mode != DUPLEX || deviceId == id ) ) { RtAudioCallback callback = (RtAudioCallback) info->callback; handle->stopStream = callback(stream_.userBuffer, stream_.bufferSize, info->userData); if ( handle->xrun == true ) { handle->xrun = false; MUTEX_UNLOCK(&stream_.mutex); return; } } if ( stream_.mode == OUTPUT || ( stream_.mode == DUPLEX && deviceId == id ) ) { if (stream_.doConvertBuffer[0]) { if ( !stream_.deInterleave[0] ) stream_.deviceBuffer = (char *) outBufferList->mBuffers[handle->index[0]].mData; else stream_.deviceBuffer = handle->deviceBuffer; convertBuffer( stream_.deviceBuffer, stream_.userBuffer, stream_.convertInfo[0] ); if ( stream_.doByteSwap[0] ) byteSwapBuffer(stream_.deviceBuffer, stream_.bufferSize * stream_.nDeviceChannels[0], stream_.deviceFormat[0]); if ( stream_.deInterleave[0] ) { int bufferBytes = outBufferList->mBuffers[handle->index[0]].mDataByteSize; for ( int i=0; imBuffers[handle->index[0]+i].mData, &stream_.deviceBuffer[i*bufferBytes], bufferBytes ); } } } else { if (stream_.doByteSwap[0]) byteSwapBuffer(stream_.userBuffer, stream_.bufferSize * stream_.nUserChannels[0], stream_.userFormat); memcpy(outBufferList->mBuffers[handle->index[0]].mData, stream_.userBuffer, outBufferList->mBuffers[handle->index[0]].mDataByteSize ); } } id = *( (AudioDeviceID *) devices_[stream_.device[1]].apiDeviceId ); if ( stream_.mode == INPUT || ( stream_.mode == DUPLEX && deviceId == id ) ) { if (stream_.doConvertBuffer[1]) { if ( stream_.deInterleave[1] ) { stream_.deviceBuffer = (char *) handle->deviceBuffer; int bufferBytes = inBufferList->mBuffers[handle->index[1]].mDataByteSize; for ( int i=0; imBuffers[handle->index[1]+i].mData, bufferBytes ); } } else stream_.deviceBuffer = (char *) inBufferList->mBuffers[handle->index[1]].mData; if ( stream_.doByteSwap[1] ) byteSwapBuffer(stream_.deviceBuffer, stream_.bufferSize * stream_.nDeviceChannels[1], stream_.deviceFormat[1]); convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] ); } else { memcpy(stream_.userBuffer, inBufferList->mBuffers[handle->index[1]].mData, inBufferList->mBuffers[handle->index[1]].mDataByteSize ); if (stream_.doByteSwap[1]) byteSwapBuffer(stream_.userBuffer, stream_.bufferSize * stream_.nUserChannels[1], stream_.userFormat); } } if ( !info->usingCallback && (stream_.mode != DUPLEX || deviceId == id ) ) pthread_cond_signal(&handle->condition); MUTEX_UNLOCK(&stream_.mutex); } void RtApiCore :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); if ( stream_.callbackInfo.usingCallback ) { sprintf(message_, "RtApiCore: A callback is already set for this stream!"); error(RtError::WARNING); return; } stream_.callbackInfo.callback = (void *) callback; stream_.callbackInfo.userData = userData; stream_.callbackInfo.usingCallback = true; } void RtApiCore :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; stream_.callbackInfo.userData = NULL; stream_.state = STREAM_STOPPED; stream_.callbackInfo.callback = NULL; MUTEX_UNLOCK(&stream_.mutex); } } //******************** End of __MACOSX_CORE__ *********************// #endif #if defined(__LINUX_JACK__) // JACK is a low-latency audio server, written primarily for the // GNU/Linux operating system. It can connect a number of different // applications to an audio device, as well as allowing them to share // audio between themselves. // // The JACK server must be running before RtApiJack can be instantiated. // RtAudio will report just a single "device", which is the JACK audio // server. The JACK server is typically started in a terminal as follows: // // .jackd -d alsa -d hw:0 // // or through an interface program such as qjackctl. Many of the // parameters normally set for a stream are fixed by the JACK server // and can be specified when the JACK server is started. In // particular, // // .jackd -d alsa -d hw:0 -r 44100 -p 512 -n 4 // // specifies a sample rate of 44100 Hz, a buffer size of 512 sample // frames, and number of buffers = 4. Once the server is running, it // is not possible to override these values. If the values are not // specified in the command-line, the JACK server uses default values. #include #include // A structure to hold various information related to the Jack API // implementation. struct JackHandle { jack_client_t *client; jack_port_t **ports[2]; bool clientOpen; bool stopStream; pthread_cond_t condition; JackHandle() :client(0), clientOpen(false), stopStream(false) {} }; std::string jackmsg; static void jackerror (const char *desc) { jackmsg.erase(); jackmsg.append( desc, strlen(desc)+1 ); } RtApiJack :: RtApiJack() { this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiJack: no Linux Jack server found or connection error (jack: %s)!", jackmsg.c_str()); error(RtError::NO_DEVICES_FOUND); } } RtApiJack :: ~RtApiJack() { if ( stream_.mode != UNINITIALIZED ) closeStream(); } void RtApiJack :: initialize(void) { nDevices_ = 0; // Tell the jack server to call jackerror() when it experiences an // error. This function saves the error message for subsequent // reporting via the normal RtAudio error function. jack_set_error_function( jackerror ); // Look for jack server and try to become a client. jack_client_t *client; if ( (client = jack_client_new( "RtApiJack" )) == 0) return; RtApiDevice device; // Determine the name of the device. device.name = "Jack Server"; devices_.push_back(device); nDevices_++; jack_client_close(client); } void RtApiJack :: probeDeviceInfo(RtApiDevice *info) { // Look for jack server and try to become a client. jack_client_t *client; if ( (client = jack_client_new( "RtApiJack" )) == 0) { sprintf(message_, "RtApiJack: error connecting to Linux Jack server in probeDeviceInfo() (jack: %s)!", jackmsg.c_str()); error(RtError::WARNING); return; } // Get the current jack server sample rate. info->sampleRates.clear(); info->sampleRates.push_back( jack_get_sample_rate(client) ); // Count the available ports as device channels. Jack "input ports" // equal RtAudio output channels. const char **ports; char *port; unsigned int nChannels = 0; ports = jack_get_ports( client, NULL, NULL, JackPortIsInput ); if ( ports ) { port = (char *) ports[nChannels]; while ( port ) port = (char *) ports[++nChannels]; free( ports ); info->maxOutputChannels = nChannels; info->minOutputChannels = 1; } // Jack "output ports" equal RtAudio input channels. nChannels = 0; ports = jack_get_ports( client, NULL, NULL, JackPortIsOutput ); if ( ports ) { port = (char *) ports[nChannels]; while ( port ) port = (char *) ports[++nChannels]; free( ports ); info->maxInputChannels = nChannels; info->minInputChannels = 1; } if (info->maxOutputChannels == 0 && info->maxInputChannels == 0) { jack_client_close(client); sprintf(message_, "RtApiJack: error determining jack input/output channels!"); error(RtError::DEBUG_WARNING); return; } if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) { info->hasDuplexSupport = true; info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ? info->maxInputChannels : info->maxOutputChannels; info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ? info->minInputChannels : info->minOutputChannels; } // Get the jack data format type. There isn't much documentation // regarding supported data formats in jack. I'm assuming here that // the default type will always be a floating-point type, of length // equal to either 4 or 8 bytes. int sample_size = sizeof( jack_default_audio_sample_t ); if ( sample_size == 4 ) info->nativeFormats = RTAUDIO_FLOAT32; else if ( sample_size == 8 ) info->nativeFormats = RTAUDIO_FLOAT64; // Check that we have a supported format if (info->nativeFormats == 0) { jack_client_close(client); sprintf(message_, "RtApiJack: error determining jack server data format!"); error(RtError::DEBUG_WARNING); return; } jack_client_close(client); info->probed = true; } int jackCallbackHandler(jack_nframes_t nframes, void *infoPointer) { CallbackInfo *info = (CallbackInfo *) infoPointer; RtApiJack *object = (RtApiJack *) info->object; try { object->callbackEvent( (unsigned long) nframes ); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiJack: callback handler error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_poplog(); return 0; } return 0; } void jackShutdown(void *infoPointer) { CallbackInfo *info = (CallbackInfo *) infoPointer; JackHandle *handle = (JackHandle *) info->apiInfo; handle->clientOpen = false; RtApiJack *object = (RtApiJack *) info->object; // Check current stream state. If stopped, then we'll assume this // was called as a result of a call to RtApiJack::stopStream (the // deactivation of a client handle causes this function to be called). // If not, we'll assume the Jack server is shutting down or some // other problem occurred and we should close the stream. if ( object->getStreamState() == RtApi::STREAM_STOPPED ) return; try { object->closeStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiJack: jackShutdown error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_poplog(); return; } EM_log( CK_LOG_SYSTEM, "(via rtaudio): the Jack server is shutting down this client..." ); EM_log( CK_LOG_SYSTEM, "...stream stopped and closed" ); } int jackXrun( void * ) { EM_log( CK_LOG_INFO, "(via rtaudio): Jack audio overrun/underrun reported..." ); return 0; } bool RtApiJack :: probeDeviceOpen(int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers) { // Compare the jack server channels to the requested number of channels. if ( (mode == OUTPUT && devices_[device].maxOutputChannels < channels ) || (mode == INPUT && devices_[device].maxInputChannels < channels ) ) { sprintf(message_, "RtApiJack: the Jack server does not support requested channels!"); error(RtError::DEBUG_WARNING); return FAILURE; } JackHandle *handle = (JackHandle *) stream_.apiHandle; // Look for jack server and try to become a client (only do once per stream). char label[32]; jack_client_t *client = 0; if ( mode == OUTPUT || (mode == INPUT && stream_.mode != OUTPUT) ) { snprintf(label, 32, "RtApiJack"); if ( (client = jack_client_new( (const char *) label )) == 0) { sprintf(message_, "RtApiJack: cannot connect to Linux Jack server in probeDeviceOpen() (jack: %s)!", jackmsg.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } } else { // The handle must have been created on an earlier pass. client = handle->client; } // First, check the jack server sample rate. int jack_rate; jack_rate = (int) jack_get_sample_rate(client); if ( sampleRate != jack_rate ) { jack_client_close(client); sprintf( message_, "RtApiJack: the requested sample rate (%d) is different than the JACK server rate (%d).", sampleRate, jack_rate ); error(RtError::DEBUG_WARNING); return FAILURE; } stream_.sampleRate = jack_rate; // The jack server seems to support just a single floating-point // data type. Since we already checked it before, just use what we // found then. stream_.deviceFormat[mode] = devices_[device].nativeFormats; stream_.userFormat = format; // Jack always uses non-interleaved buffers. We'll need to // de-interleave if we have more than one channel. stream_.deInterleave[mode] = false; if ( channels > 1 ) stream_.deInterleave[mode] = true; // Jack always provides host byte-ordered data. stream_.doByteSwap[mode] = false; // Get the buffer size. The buffer size and number of buffers // (periods) is set when the jack server is started. stream_.bufferSize = (int) jack_get_buffer_size(client); *bufferSize = stream_.bufferSize; stream_.nDeviceChannels[mode] = channels; stream_.nUserChannels[mode] = channels; stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.deInterleave[mode]) stream_.doConvertBuffer[mode] = true; // Allocate our JackHandle structure for the stream. if ( handle == 0 ) { handle = (JackHandle *) calloc(1, sizeof(JackHandle)); if ( handle == NULL ) { sprintf(message_, "RtApiJack: error allocating JackHandle memory (%s).", devices_[device].name.c_str()); goto error; } handle->ports[0] = 0; handle->ports[1] = 0; if ( pthread_cond_init(&handle->condition, NULL) ) { sprintf(message_, "RtApiJack: error initializing pthread condition variable!"); goto error; } stream_.apiHandle = (void *) handle; handle->client = client; handle->clientOpen = true; } // Allocate necessary internal buffers. if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { sprintf(message_, "RtApiJack: error allocating user buffer memory (%s).", devices_[device].name.c_str()); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiJack: error allocating device buffer memory (%s).", devices_[device].name.c_str()); goto error; } } } // Allocate memory for the Jack ports (channels) identifiers. handle->ports[mode] = (jack_port_t **) malloc (sizeof (jack_port_t *) * channels); if ( handle->ports[mode] == NULL ) { sprintf(message_, "RtApiJack: error allocating port handle memory (%s).", devices_[device].name.c_str()); goto error; } stream_.device[mode] = device; stream_.state = STREAM_STOPPED; stream_.callbackInfo.usingCallback = false; stream_.callbackInfo.object = (void *) this; stream_.callbackInfo.apiInfo = (void *) handle; if ( stream_.mode == OUTPUT && mode == INPUT ) // We had already set up the stream for output. stream_.mode = DUPLEX; else { stream_.mode = mode; jack_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo ); jack_set_xrun_callback( handle->client, jackXrun, NULL ); jack_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo ); } // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; kcondition); if ( handle->clientOpen == true ) jack_client_close(handle->client); if ( handle->ports[0] ) free(handle->ports[0]); if ( handle->ports[1] ) free(handle->ports[1]); free( handle ); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } error(RtError::DEBUG_WARNING); return FAILURE; } void RtApiJack :: closeStream() { // We don't want an exception to be thrown here because this // function is called by our class destructor. So, do our own // stream check. if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtApiJack::closeStream(): no open stream to close!"); error(RtError::WARNING); return; } JackHandle *handle = (JackHandle *) stream_.apiHandle; if ( handle && handle->clientOpen == true ) { if (stream_.state == STREAM_RUNNING) jack_deactivate(handle->client); jack_client_close(handle->client); } if ( handle ) { if ( handle->ports[0] ) free(handle->ports[0]); if ( handle->ports[1] ) free(handle->ports[1]); pthread_cond_destroy(&handle->condition); free( handle ); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } if (stream_.deviceBuffer) { free(stream_.deviceBuffer); stream_.deviceBuffer = 0; } stream_.mode = UNINITIALIZED; } void RtApiJack :: startStream() { verifyStream(); if (stream_.state == STREAM_RUNNING) return; MUTEX_LOCK(&stream_.mutex); char label[64]; JackHandle *handle = (JackHandle *) stream_.apiHandle; if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { for ( int i=0; iports[0][i] = jack_port_register(handle->client, (const char *)label, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); } } if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { for ( int i=0; iports[1][i] = jack_port_register(handle->client, (const char *)label, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); } } if (jack_activate(handle->client)) { sprintf(message_, "RtApiJack: unable to activate JACK client!"); error(RtError::SYSTEM_ERROR); } const char **ports; int result; // Get the list of available ports. if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { ports = jack_get_ports(handle->client, NULL, NULL, JackPortIsPhysical|JackPortIsInput); if ( ports == NULL) { sprintf(message_, "RtApiJack: error determining available jack input ports!"); error(RtError::SYSTEM_ERROR); } // Now make the port connections. Since RtAudio wasn't designed to // allow the user to select particular channels of a device, we'll // just open the first "nChannels" ports. for ( int i=0; iclient, jack_port_name(handle->ports[0][i]), ports[i] ); if ( result ) { free(ports); sprintf(message_, "RtApiJack: error connecting output ports!"); error(RtError::SYSTEM_ERROR); } } free(ports); } if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { ports = jack_get_ports( handle->client, NULL, NULL, JackPortIsPhysical|JackPortIsOutput ); if ( ports == NULL) { sprintf(message_, "RtApiJack: error determining available jack output ports!"); error(RtError::SYSTEM_ERROR); } // Now make the port connections. See note above. for ( int i=0; iclient, ports[i], jack_port_name(handle->ports[1][i]) ); if ( result ) { free(ports); sprintf(message_, "RtApiJack: error connecting input ports!"); error(RtError::SYSTEM_ERROR); } } free(ports); } handle->stopStream = false; stream_.state = STREAM_RUNNING; MUTEX_UNLOCK(&stream_.mutex); } void RtApiJack :: stopStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); JackHandle *handle = (JackHandle *) stream_.apiHandle; jack_deactivate(handle->client); MUTEX_UNLOCK(&stream_.mutex); } void RtApiJack :: abortStream() { stopStream(); } void RtApiJack :: tickStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; if (stream_.callbackInfo.usingCallback) { sprintf(message_, "RtApiJack: tickStream() should not be used when a callback function is set!"); error(RtError::WARNING); return; } JackHandle *handle = (JackHandle *) stream_.apiHandle; MUTEX_LOCK(&stream_.mutex); pthread_cond_wait(&handle->condition, &stream_.mutex); MUTEX_UNLOCK(&stream_.mutex); } void RtApiJack :: callbackEvent( unsigned long nframes ) { verifyStream(); if (stream_.state == STREAM_STOPPED) return; CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; JackHandle *handle = (JackHandle *) stream_.apiHandle; if ( info->usingCallback && handle->stopStream ) { // Check if the stream should be stopped (via the previous user // callback return value). We stop the stream here, rather than // after the function call, so that output data can first be // processed. this->stopStream(); return; } MUTEX_LOCK(&stream_.mutex); // Invoke user callback first, to get fresh output data. if ( info->usingCallback ) { RtAudioCallback callback = (RtAudioCallback) info->callback; handle->stopStream = callback(stream_.userBuffer, stream_.bufferSize, info->userData); } jack_default_audio_sample_t *jackbuffer; long bufferBytes = nframes * sizeof(jack_default_audio_sample_t); if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { if (stream_.doConvertBuffer[0]) { convertBuffer( stream_.deviceBuffer, stream_.userBuffer, stream_.convertInfo[0] ); for ( int i=0; iports[0][i], (jack_nframes_t) nframes); memcpy(jackbuffer, &stream_.deviceBuffer[i*bufferBytes], bufferBytes ); } } else { // single channel only jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer(handle->ports[0][0], (jack_nframes_t) nframes); memcpy(jackbuffer, stream_.userBuffer, bufferBytes ); } } if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { if (stream_.doConvertBuffer[1]) { for ( int i=0; iports[1][i], (jack_nframes_t) nframes); memcpy(&stream_.deviceBuffer[i*bufferBytes], jackbuffer, bufferBytes ); } convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] ); } else { // single channel only jackbuffer = (jack_default_audio_sample_t *) jack_port_get_buffer(handle->ports[1][0], (jack_nframes_t) nframes); memcpy(stream_.userBuffer, jackbuffer, bufferBytes ); } } if ( !info->usingCallback ) pthread_cond_signal(&handle->condition); MUTEX_UNLOCK(&stream_.mutex); } void RtApiJack :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); if ( stream_.callbackInfo.usingCallback ) { sprintf(message_, "RtApiJack: A callback is already set for this stream!"); error(RtError::WARNING); return; } stream_.callbackInfo.callback = (void *) callback; stream_.callbackInfo.userData = userData; stream_.callbackInfo.usingCallback = true; } void RtApiJack :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; stream_.callbackInfo.userData = NULL; stream_.state = STREAM_STOPPED; stream_.callbackInfo.callback = NULL; MUTEX_UNLOCK(&stream_.mutex); } } #endif #if defined(__LINUX_ALSA__) #include #include #include // A structure to hold various information related to the ALSA API // implementation. struct AlsaHandle { snd_pcm_t *handles[2]; bool synchronized; char *tempBuffer; AlsaHandle() :synchronized(false), tempBuffer(0) {} }; extern "C" void *alsaCallbackHandler(void * ptr); RtApiAlsa :: RtApiAlsa() { this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiAlsa: no Linux ALSA audio devices found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiAlsa :: ~RtApiAlsa() { if ( stream_.mode != UNINITIALIZED ) closeStream(); } void RtApiAlsa :: initialize(void) { int card, subdevice, result; char name[64]; const char *cardId; snd_ctl_t *handle; snd_ctl_card_info_t *info; snd_ctl_card_info_alloca(&info); RtApiDevice device; // Count cards and devices nDevices_ = 0; card = -1; snd_card_next(&card); while ( card >= 0 ) { sprintf(name, "hw:%d", card); result = snd_ctl_open(&handle, name, 0); if (result < 0) { sprintf(message_, "RtApiAlsa: control open (%i): %s.", card, snd_strerror(result)); error(RtError::DEBUG_WARNING); goto next_card; } result = snd_ctl_card_info(handle, info); if (result < 0) { sprintf(message_, "RtApiAlsa: control hardware info (%i): %s.", card, snd_strerror(result)); error(RtError::DEBUG_WARNING); goto next_card; } cardId = snd_ctl_card_info_get_id(info); subdevice = -1; while (1) { result = snd_ctl_pcm_next_device(handle, &subdevice); if (result < 0) { sprintf(message_, "RtApiAlsa: control next device (%i): %s.", card, snd_strerror(result)); error(RtError::DEBUG_WARNING); break; } if (subdevice < 0) break; sprintf( name, "hw:%d,%d", card, subdevice ); // If a cardId exists and it contains at least one non-numeric // character, use it to identify the device. This avoids a bug // in ALSA such that a numeric string is interpreted as a device // number. for ( unsigned int i=0; iname.c_str(), 64 ); card = strtok(name, ","); err = snd_ctl_open(&chandle, card, SND_CTL_NONBLOCK); if (err < 0) { sprintf(message_, "RtApiAlsa: control open (%s): %s.", card, snd_strerror(err)); error(RtError::DEBUG_WARNING); return; } unsigned int dev = (unsigned int) atoi( strtok(NULL, ",") ); // First try for playback stream = SND_PCM_STREAM_PLAYBACK; snd_pcm_info_set_device(pcminfo, dev); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); if ((err = snd_ctl_pcm_info(chandle, pcminfo)) < 0) { if (err == -ENOENT) { sprintf(message_, "RtApiAlsa: pcm device (%s) doesn't handle output!", info->name.c_str()); error(RtError::DEBUG_WARNING); } else { sprintf(message_, "RtApiAlsa: snd_ctl_pcm_info error for device (%s) output: %s", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); } goto capture_probe; } err = snd_pcm_open(&handle, info->name.c_str(), stream, open_mode | SND_PCM_NONBLOCK ); if (err < 0) { if ( err == EBUSY ) sprintf(message_, "RtApiAlsa: pcm playback device (%s) is busy: %s.", info->name.c_str(), snd_strerror(err)); else sprintf(message_, "RtApiAlsa: pcm playback open (%s) error: %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); goto capture_probe; } // We have an open device ... allocate the parameter structure. err = snd_pcm_hw_params_any(handle, params); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); goto capture_probe; } // Get output channel information. unsigned int value; err = snd_pcm_hw_params_get_channels_min(params, &value); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware minimum channel probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); goto capture_probe; } info->minOutputChannels = value; err = snd_pcm_hw_params_get_channels_max(params, &value); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware maximum channel probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); goto capture_probe; } info->maxOutputChannels = value; snd_pcm_close(handle); capture_probe: // Now try for capture stream = SND_PCM_STREAM_CAPTURE; snd_pcm_info_set_stream(pcminfo, stream); err = snd_ctl_pcm_info(chandle, pcminfo); snd_ctl_close(chandle); if ( err < 0 ) { if (err == -ENOENT) { sprintf(message_, "RtApiAlsa: pcm device (%s) doesn't handle input!", info->name.c_str()); error(RtError::DEBUG_WARNING); } else { sprintf(message_, "RtApiAlsa: snd_ctl_pcm_info error for device (%s) input: %s", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); } if (info->maxOutputChannels == 0) // didn't open for playback either ... device invalid return; goto probe_parameters; } err = snd_pcm_open(&handle, info->name.c_str(), stream, open_mode | SND_PCM_NONBLOCK); if (err < 0) { if ( err == EBUSY ) sprintf(message_, "RtApiAlsa: pcm capture device (%s) is busy: %s.", info->name.c_str(), snd_strerror(err)); else sprintf(message_, "RtApiAlsa: pcm capture open (%s) error: %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); if (info->maxOutputChannels == 0) // didn't open for playback either ... device invalid return; goto probe_parameters; } // We have an open capture device ... allocate the parameter structure. err = snd_pcm_hw_params_any(handle, params); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); if (info->maxOutputChannels > 0) goto probe_parameters; else return; } // Get input channel information. err = snd_pcm_hw_params_get_channels_min(params, &value); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware minimum in channel probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); if (info->maxOutputChannels > 0) goto probe_parameters; else return; } info->minInputChannels = value; err = snd_pcm_hw_params_get_channels_max(params, &value); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware maximum in channel probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); if (info->maxOutputChannels > 0) goto probe_parameters; else return; } info->maxInputChannels = value; snd_pcm_close(handle); // If device opens for both playback and capture, we determine the channels. if (info->maxOutputChannels == 0 || info->maxInputChannels == 0) goto probe_parameters; info->hasDuplexSupport = true; info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ? info->maxInputChannels : info->maxOutputChannels; info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ? info->minInputChannels : info->minOutputChannels; probe_parameters: // At this point, we just need to figure out the supported data // formats and sample rates. We'll proceed by opening the device in // the direction with the maximum number of channels, or playback if // they are equal. This might limit our sample rate options, but so // be it. if (info->maxOutputChannels >= info->maxInputChannels) stream = SND_PCM_STREAM_PLAYBACK; else stream = SND_PCM_STREAM_CAPTURE; err = snd_pcm_open(&handle, info->name.c_str(), stream, open_mode); if (err < 0) { sprintf(message_, "RtApiAlsa: pcm (%s) won't reopen during probe: %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); return; } // We have an open device ... allocate the parameter structure. err = snd_pcm_hw_params_any(handle, params); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: hardware reopen probe error (%s): %s.", info->name.c_str(), snd_strerror(err)); error(RtError::DEBUG_WARNING); return; } // Test our discrete set of sample rate values. int dir = 0; info->sampleRates.clear(); for (unsigned int i=0; isampleRates.push_back(SAMPLE_RATES[i]); } if (info->sampleRates.size() == 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: no supported sample rates found for device (%s).", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Probe the supported data formats ... we don't care about endian-ness just yet snd_pcm_format_t format; info->nativeFormats = 0; format = SND_PCM_FORMAT_S8; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_SINT8; format = SND_PCM_FORMAT_S16; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_SINT16; format = SND_PCM_FORMAT_S24; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_SINT24; format = SND_PCM_FORMAT_S32; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_SINT32; format = SND_PCM_FORMAT_FLOAT; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_FLOAT32; format = SND_PCM_FORMAT_FLOAT64; if (snd_pcm_hw_params_test_format(handle, params, format) == 0) info->nativeFormats |= RTAUDIO_FLOAT64; // Check that we have at least one supported format if (info->nativeFormats == 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: pcm device (%s) data format not supported by RtAudio.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // That's all ... close the device and return snd_pcm_close(handle); info->probed = true; return; } bool RtApiAlsa :: probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ) { #if defined(__RTAUDIO_DEBUG__) snd_output_t *out; snd_output_stdio_attach(&out, stderr, 0); #endif // I'm not using the "plug" interface ... too much inconsistent behavior. const char *name = devices_[device].name.c_str(); snd_pcm_stream_t alsa_stream; if (mode == OUTPUT) alsa_stream = SND_PCM_STREAM_PLAYBACK; else alsa_stream = SND_PCM_STREAM_CAPTURE; int err; snd_pcm_t *handle; int alsa_open_mode = SND_PCM_ASYNC; err = snd_pcm_open(&handle, name, alsa_stream, alsa_open_mode); if (err < 0) { sprintf(message_,"RtApiAlsa: pcm device (%s) won't open: %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Fill the parameter structure. snd_pcm_hw_params_t *hw_params; snd_pcm_hw_params_alloca(&hw_params); err = snd_pcm_hw_params_any(handle, hw_params); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error getting parameter handle (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } #if defined(__RTAUDIO_DEBUG__) fprintf(stderr, "\nRtApiAlsa: dump hardware params just after device open:\n\n"); snd_pcm_hw_params_dump(hw_params, out); #endif // Set access ... try interleaved access first, then non-interleaved if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED) ) { err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); } else if ( !snd_pcm_hw_params_test_access( handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED) ) { err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_NONINTERLEAVED); stream_.deInterleave[mode] = true; } else { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: device (%s) access not supported by RtAudio.", name); error(RtError::DEBUG_WARNING); return FAILURE; } if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting access ( (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Determine how to set the device format. stream_.userFormat = format; snd_pcm_format_t device_format = SND_PCM_FORMAT_UNKNOWN; if (format == RTAUDIO_SINT8) device_format = SND_PCM_FORMAT_S8; else if (format == RTAUDIO_SINT16) device_format = SND_PCM_FORMAT_S16; else if (format == RTAUDIO_SINT24) device_format = SND_PCM_FORMAT_S24; else if (format == RTAUDIO_SINT32) device_format = SND_PCM_FORMAT_S32; else if (format == RTAUDIO_FLOAT32) device_format = SND_PCM_FORMAT_FLOAT; else if (format == RTAUDIO_FLOAT64) device_format = SND_PCM_FORMAT_FLOAT64; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = format; goto set_format; } // The user requested format is not natively supported by the device. device_format = SND_PCM_FORMAT_FLOAT64; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; goto set_format; } device_format = SND_PCM_FORMAT_FLOAT; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; goto set_format; } device_format = SND_PCM_FORMAT_S32; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_SINT32; goto set_format; } device_format = SND_PCM_FORMAT_S24; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_SINT24; goto set_format; } device_format = SND_PCM_FORMAT_S16; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_SINT16; goto set_format; } device_format = SND_PCM_FORMAT_S8; if (snd_pcm_hw_params_test_format(handle, hw_params, device_format) == 0) { stream_.deviceFormat[mode] = RTAUDIO_SINT8; goto set_format; } // If we get here, no supported format was found. sprintf(message_,"RtApiAlsa: pcm device (%s) data format not supported by RtAudio.", name); snd_pcm_close(handle); error(RtError::DEBUG_WARNING); return FAILURE; set_format: err = snd_pcm_hw_params_set_format(handle, hw_params, device_format); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting format (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Determine whether byte-swaping is necessary. stream_.doByteSwap[mode] = false; if (device_format != SND_PCM_FORMAT_S8) { err = snd_pcm_format_cpu_endian(device_format); if (err == 0) stream_.doByteSwap[mode] = true; else if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error getting format endian-ness (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } } // Set the sample rate. err = snd_pcm_hw_params_set_rate(handle, hw_params, (unsigned int)sampleRate, 0); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting sample rate (%d) on device (%s): %s.", sampleRate, name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Determine the number of channels for this device. We support a possible // minimum device channel number > than the value requested by the user. stream_.nUserChannels[mode] = channels; unsigned int value; err = snd_pcm_hw_params_get_channels_max(hw_params, &value); int device_channels = value; if (err < 0 || device_channels < channels) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: channels (%d) not supported by device (%s).", channels, name); error(RtError::DEBUG_WARNING); return FAILURE; } err = snd_pcm_hw_params_get_channels_min(hw_params, &value); if (err < 0 ) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error getting min channels count on device (%s).", name); error(RtError::DEBUG_WARNING); return FAILURE; } device_channels = value; if (device_channels < channels) device_channels = channels; stream_.nDeviceChannels[mode] = device_channels; // Set the device channels. err = snd_pcm_hw_params_set_channels(handle, hw_params, device_channels); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting channels (%d) on device (%s): %s.", device_channels, name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the buffer number, which in ALSA is referred to as the "period". int dir; unsigned int periods = numberOfBuffers; // Even though the hardware might allow 1 buffer, it won't work reliably. if (periods < 2) periods = 2; err = snd_pcm_hw_params_set_periods_near(handle, hw_params, &periods, &dir); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting periods (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the buffer (or period) size. snd_pcm_uframes_t period_size = *bufferSize; err = snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, &dir); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error setting period size (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } *bufferSize = period_size; // If attempting to setup a duplex stream, the bufferSize parameter // MUST be the same in both directions! if ( stream_.mode == OUTPUT && mode == INPUT && *bufferSize != stream_.bufferSize ) { sprintf( message_, "RtApiAlsa: error setting buffer size for duplex stream on device (%s).", name ); error(RtError::DEBUG_WARNING); return FAILURE; } stream_.bufferSize = *bufferSize; // Install the hardware configuration err = snd_pcm_hw_params(handle, hw_params); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtApiAlsa: error installing hardware configuration (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } #if defined(__RTAUDIO_DEBUG__) fprintf(stderr, "\nRtApiAlsa: dump hardware params after installation:\n\n"); snd_pcm_hw_params_dump(hw_params, out); #endif // Set the software configuration to fill buffers with zeros and prevent device stopping on xruns. snd_pcm_sw_params_t *sw_params = NULL; snd_pcm_sw_params_alloca( &sw_params ); snd_pcm_sw_params_current( handle, sw_params ); snd_pcm_sw_params_set_start_threshold( handle, sw_params, *bufferSize ); snd_pcm_sw_params_set_stop_threshold( handle, sw_params, 0x7fffffff ); snd_pcm_sw_params_set_silence_threshold( handle, sw_params, 0 ); snd_pcm_sw_params_set_silence_size( handle, sw_params, INT_MAX ); err = snd_pcm_sw_params( handle, sw_params ); if (err < 0) { snd_pcm_close(handle); sprintf(message_, "RtAudio: ALSA error installing software configuration (%s): %s.", name, snd_strerror(err)); error(RtError::DEBUG_WARNING); return FAILURE; } #if defined(__RTAUDIO_DEBUG__) fprintf(stderr, "\nRtApiAlsa: dump software params after installation:\n\n"); snd_pcm_sw_params_dump(sw_params, out); #endif // Allocate the ApiHandle if necessary and then save. AlsaHandle *apiInfo = 0; if ( stream_.apiHandle == 0 ) { apiInfo = (AlsaHandle *) new AlsaHandle; stream_.apiHandle = (void *) apiInfo; apiInfo->handles[0] = 0; apiInfo->handles[1] = 0; } else { apiInfo = (AlsaHandle *) stream_.apiHandle; } apiInfo->handles[mode] = handle; // Set flags for buffer conversion stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] > 1 && stream_.deInterleave[mode]) stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); if (apiInfo->tempBuffer) free(apiInfo->tempBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); apiInfo->tempBuffer = (char *) calloc(buffer_bytes, 1); if ( stream_.userBuffer == NULL || apiInfo->tempBuffer == NULL ) { sprintf(message_, "RtApiAlsa: error allocating user buffer memory (%s).", devices_[device].name.c_str()); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiAlsa: error allocating device buffer memory (%s).", devices_[device].name.c_str()); goto error; } } } stream_.device[mode] = device; stream_.state = STREAM_STOPPED; if ( stream_.mode == OUTPUT && mode == INPUT ) { // We had already set up an output stream. stream_.mode = DUPLEX; // Link the streams if possible. apiInfo->synchronized = false; if (snd_pcm_link( apiInfo->handles[0], apiInfo->handles[1] ) == 0) apiInfo->synchronized = true; else { sprintf(message_, "RtApiAlsa: unable to synchronize input and output streams (%s).", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); } } else stream_.mode = mode; stream_.nBuffers = periods; stream_.sampleRate = sampleRate; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; khandles[0]) snd_pcm_close(apiInfo->handles[0]); if (apiInfo->handles[1]) snd_pcm_close(apiInfo->handles[1]); if ( apiInfo->tempBuffer ) free(apiInfo->tempBuffer); delete apiInfo; stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } error(RtError::DEBUG_WARNING); return FAILURE; } void RtApiAlsa :: closeStream() { // We don't want an exception to be thrown here because this // function is called by our class destructor. So, do our own // stream check. if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtApiAlsa::closeStream(): no open stream to close!"); error(RtError::WARNING); return; } AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; if (stream_.state == STREAM_RUNNING) { if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) snd_pcm_drop(apiInfo->handles[0]); if (stream_.mode == INPUT || stream_.mode == DUPLEX) snd_pcm_drop(apiInfo->handles[1]); stream_.state = STREAM_STOPPED; } if (stream_.callbackInfo.usingCallback) { stream_.callbackInfo.usingCallback = false; pthread_join(stream_.callbackInfo.thread, NULL); } if (apiInfo) { if (apiInfo->handles[0]) snd_pcm_close(apiInfo->handles[0]); if (apiInfo->handles[1]) snd_pcm_close(apiInfo->handles[1]); free(apiInfo->tempBuffer); delete apiInfo; stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } if (stream_.deviceBuffer) { free(stream_.deviceBuffer); stream_.deviceBuffer = 0; } stream_.mode = UNINITIALIZED; } void RtApiAlsa :: startStream() { // This method calls snd_pcm_prepare if the device isn't already in that state. verifyStream(); if (stream_.state == STREAM_RUNNING) return; MUTEX_LOCK(&stream_.mutex); int err; snd_pcm_state_t state; AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { state = snd_pcm_state(handle[0]); if (state != SND_PCM_STATE_PREPARED) { err = snd_pcm_prepare(handle[0]); if (err < 0) { sprintf(message_, "RtApiAlsa: error preparing pcm device (%s): %s.", devices_[stream_.device[0]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } } if ( (stream_.mode == INPUT || stream_.mode == DUPLEX) && !apiInfo->synchronized ) { state = snd_pcm_state(handle[1]); if (state != SND_PCM_STATE_PREPARED) { err = snd_pcm_prepare(handle[1]); if (err < 0) { sprintf(message_, "RtApiAlsa: error preparing pcm device (%s): %s.", devices_[stream_.device[1]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } } stream_.state = STREAM_RUNNING; MUTEX_UNLOCK(&stream_.mutex); } void RtApiAlsa :: stopStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); int err; AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { err = snd_pcm_drain(handle[0]); if (err < 0) { sprintf(message_, "RtApiAlsa: error draining pcm device (%s): %s.", devices_[stream_.device[0]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } if ( (stream_.mode == INPUT || stream_.mode == DUPLEX) && !apiInfo->synchronized ) { err = snd_pcm_drain(handle[1]); if (err < 0) { sprintf(message_, "RtApiAlsa: error draining pcm device (%s): %s.", devices_[stream_.device[1]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } MUTEX_UNLOCK(&stream_.mutex); } void RtApiAlsa :: abortStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); int err; AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { err = snd_pcm_drop(handle[0]); if (err < 0) { sprintf(message_, "RtApiAlsa: error draining pcm device (%s): %s.", devices_[stream_.device[0]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } if ( (stream_.mode == INPUT || stream_.mode == DUPLEX) && !apiInfo->synchronized ) { err = snd_pcm_drop(handle[1]); if (err < 0) { sprintf(message_, "RtApiAlsa: error draining pcm device (%s): %s.", devices_[stream_.device[1]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } MUTEX_UNLOCK(&stream_.mutex); } int RtApiAlsa :: streamWillBlock() { verifyStream(); if (stream_.state == STREAM_STOPPED) return 0; MUTEX_LOCK(&stream_.mutex); int err = 0, frames = 0; AlsaHandle *apiInfo = (AlsaHandle *) stream_.apiHandle; snd_pcm_t **handle = (snd_pcm_t **) apiInfo->handles; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { err = snd_pcm_avail_update(handle[0]); if (err < 0) { sprintf(message_, "RtApiAlsa: error getting available frames for device (%s): %s.", devices_[stream_.device[0]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } } frames = err; if (stream_.mode == INPUT || stream_.mode == DUPLEX) { err = snd_pcm_avail_update(handle[1]); if (err < 0) { sprintf(message_, "RtApiAlsa: error getting available frames for device (%s): %s.", devices_[stream_.device[1]].name.c_str(), snd_strerror(err)); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } if (frames > err) frames = err; } frames = stream_.bufferSize - frames; if (frames < 0) frames = 0; MUTEX_UNLOCK(&stream_.mutex); return frames; } void RtApiAlsa :: tickStream() { verifyStream(); int stopStream = 0; if (stream_.state == STREAM_STOPPED) { if (stream_.callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds return; } else if (stream_.callbackInfo.usingCallback) { RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; stopStream = callback(stream_.userBuffer, stream_.bufferSize, stream_.callbackInfo.userData); } MUTEX_LOCK(&stream_.mutex); // The state might change while waiting on a mutex. if (stream_.state == STREAM_STOPPED) goto unlock; int err; char *buffer; int channels; AlsaHandle *apiInfo; snd_pcm_t **handle; RtAudioFormat format; apiInfo = (AlsaHandle *) stream_.apiHandle; handle = (snd_pcm_t **) apiInfo->handles; if ( stream_.mode == DUPLEX ) { // In duplex mode, we need to make the snd_pcm_read call before // the snd_pcm_write call in order to avoid under/over runs. So, // copy the userData to our temporary buffer. int bufferBytes; bufferBytes = stream_.bufferSize * stream_.nUserChannels[0] * formatBytes(stream_.userFormat); memcpy( apiInfo->tempBuffer, stream_.userBuffer, bufferBytes ); } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { // Setup parameters. if (stream_.doConvertBuffer[1]) { buffer = stream_.deviceBuffer; channels = stream_.nDeviceChannels[1]; format = stream_.deviceFormat[1]; } else { buffer = stream_.userBuffer; channels = stream_.nUserChannels[1]; format = stream_.userFormat; } // Read samples from device in interleaved/non-interleaved format. if (stream_.deInterleave[1]) { void *bufs[channels]; size_t offset = stream_.bufferSize * formatBytes(format); for (int i=0; itempBuffer, stream_.convertInfo[0] ); else convertBuffer( buffer, stream_.userBuffer, stream_.convertInfo[0] ); channels = stream_.nDeviceChannels[0]; format = stream_.deviceFormat[0]; } else { if ( stream_.mode == DUPLEX ) buffer = apiInfo->tempBuffer; else buffer = stream_.userBuffer; channels = stream_.nUserChannels[0]; format = stream_.userFormat; } // Do byte swapping if necessary. if (stream_.doByteSwap[0]) byteSwapBuffer(buffer, stream_.bufferSize * channels, format); // Write samples to device in interleaved/non-interleaved format. if (stream_.deInterleave[0]) { void *bufs[channels]; size_t offset = stream_.bufferSize * formatBytes(format); for (int i=0; istopStream(); } void RtApiAlsa :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; if ( info->usingCallback ) { sprintf(message_, "RtApiAlsa: A callback is already set for this stream!"); error(RtError::WARNING); return; } info->callback = (void *) callback; info->userData = userData; info->usingCallback = true; info->object = (void *) this; // Set the thread attributes for joinable and realtime scheduling // priority. The higher priority will only take affect if the // program is run as root or suid. pthread_attr_t attr; pthread_attr_init(&attr); // chuck // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // pthread_attr_setschedpolicy(&attr, SCHED_RR); int err = pthread_create(&info->thread, &attr, alsaCallbackHandler, &stream_.callbackInfo); pthread_attr_destroy(&attr); if (err) { info->usingCallback = false; sprintf(message_, "RtApiAlsa: error starting callback thread!"); error(RtError::THREAD_ERROR); } } void RtApiAlsa :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; pthread_join(stream_.callbackInfo.thread, NULL); stream_.callbackInfo.thread = 0; stream_.callbackInfo.callback = NULL; stream_.callbackInfo.userData = NULL; MUTEX_UNLOCK(&stream_.mutex); } } extern "C" void *alsaCallbackHandler(void *ptr) { CallbackInfo *info = (CallbackInfo *) ptr; RtApiAlsa *object = (RtApiAlsa *) info->object; bool *usingCallback = &info->usingCallback; while ( *usingCallback ) { try { object->tickStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiAlsa: callback thread error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_log( CK_LOG_INFO, "closing thread..." ); EM_poplog(); break; } } pthread_exit(NULL); } //******************** End of __LINUX_ALSA__ *********************// #endif #if defined(__WINDOWS_ASIO__) // ASIO API on Windows // The ASIO API is designed around a callback scheme, so this // implementation is similar to that used for OS-X CoreAudio and Linux // Jack. The primary constraint with ASIO is that it only allows // access to a single driver at a time. Thus, it is not possible to // have more than one simultaneous RtAudio stream. // // This implementation also requires a number of external ASIO files // and a few global variables. The ASIO callback scheme does not // allow for the passing of user data, so we must create a global // pointer to our callbackInfo structure. // // On unix systems, we make use of a pthread condition variable. // Since there is no equivalent in Windows, I hacked something based // on information found in // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. #include "asio/asiosys.h" #include "asio/asio.h" #include "asio/asiodrivers.h" #include AsioDrivers drivers; ASIOCallbacks asioCallbacks; ASIODriverInfo driverInfo; CallbackInfo *asioCallbackInfo; struct AsioHandle { bool stopStream; ASIOBufferInfo *bufferInfos; HANDLE condition; AsioHandle() :stopStream(false), bufferInfos(0) {} }; static const char*GetAsioErrorString(ASIOError result) { struct Messages { ASIOError value; const char*message; }; static Messages m[] = { { ASE_NotPresent, "Hardware input or output is not present or available." }, { ASE_HWMalfunction, "Hardware is malfunctioning." }, { ASE_InvalidParameter, "Invalid input parameter." }, { ASE_InvalidMode, "Invalid mode." }, { ASE_SPNotAdvancing, "Sample position not advancing." }, { ASE_NoClock, "Sample clock or rate cannot be determined or is not present." }, { ASE_NoMemory, "Not enough memory to complete the request." } }; for (int i = 0; i < sizeof(m)/sizeof(m[0]); ++i) { if (m[i].value == result) return m[i].message; } return "Unknown error."; } RtApiAsio :: RtApiAsio() { this->coInitialized = false; this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiAsio: no Windows ASIO audio drivers found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiAsio :: ~RtApiAsio() { if ( stream_.mode != UNINITIALIZED ) closeStream(); if ( coInitialized ) { CoUninitialize(); } } void RtApiAsio :: initialize(void) { // ASIO cannot run on a multi-threaded appartment. You can call CoInitialize beforehand, but it must be // for appartment threading (in which case, CoInitilialize will return S_FALSE here). coInitialized = false; HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { sprintf(message_,"RtApiAsio: ASIO requires a single-threaded appartment. Call CoInitializeEx(0,COINIT_APARTMENTTHREADED)"); } coInitialized = true; nDevices_ = drivers.asioGetNumDev(); if (nDevices_ <= 0) return; // Create device structures and write device driver names to each. RtApiDevice device; char name[128]; for (int i=0; iname.c_str() ) ) { sprintf(message_, "RtApiAsio: error loading driver (%s).", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } ASIOError result = ASIOInit( &driverInfo ); if ( result != ASE_OK ) { sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).", GetAsioErrorString(result), info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Determine the device channel information. long inputChannels, outputChannels; result = ASIOGetChannels( &inputChannels, &outputChannels ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: error (%s) getting input/output channel count (%s).", GetAsioErrorString(result), info->name.c_str()); error(RtError::DEBUG_WARNING); return; } info->maxOutputChannels = outputChannels; if ( outputChannels > 0 ) info->minOutputChannels = 1; info->maxInputChannels = inputChannels; if ( inputChannels > 0 ) info->minInputChannels = 1; // If device opens for both playback and capture, we determine the channels. if (info->maxOutputChannels > 0 && info->maxInputChannels > 0) { info->hasDuplexSupport = true; info->maxDuplexChannels = (info->maxOutputChannels > info->maxInputChannels) ? info->maxInputChannels : info->maxOutputChannels; info->minDuplexChannels = (info->minOutputChannels > info->minInputChannels) ? info->minInputChannels : info->minOutputChannels; } // Determine the supported sample rates. info->sampleRates.clear(); for (unsigned int i=0; isampleRates.push_back( SAMPLE_RATES[i] ); } if (info->sampleRates.size() == 0) { drivers.removeCurrentDriver(); sprintf( message_, "RtApiAsio: No supported sample rates found for driver (%s).", info->name.c_str() ); error(RtError::DEBUG_WARNING); return; } // Determine supported data types ... just check first channel and assume rest are the same. ASIOChannelInfo channelInfo; channelInfo.channel = 0; channelInfo.isInput = true; if ( info->maxInputChannels <= 0 ) channelInfo.isInput = false; result = ASIOGetChannelInfo( &channelInfo ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: error (%s) getting driver (%s) channel information.", GetAsioErrorString(result), info->name.c_str()); error(RtError::DEBUG_WARNING); return; } if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) info->nativeFormats |= RTAUDIO_SINT16; else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) info->nativeFormats |= RTAUDIO_SINT32; else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) info->nativeFormats |= RTAUDIO_FLOAT32; else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) info->nativeFormats |= RTAUDIO_FLOAT64; // Check that we have at least one supported format. if (info->nativeFormats == 0) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) data format not supported by RtAudio.", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } info->probed = true; drivers.removeCurrentDriver(); } void bufferSwitch(long index, ASIOBool processNow) { RtApiAsio *object = (RtApiAsio *) asioCallbackInfo->object; try { object->callbackEvent( index ); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiAsio: callback handler error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_poplog(): return; } return; } void sampleRateChanged(ASIOSampleRate sRate) { // The ASIO documentation says that this usually only happens during // external sync. Audio processing is not stopped by the driver, // actual sample rate might not have even changed, maybe only the // sample rate status of an AES/EBU or S/PDIF digital input at the // audio device. RtAudio *object = (RtAudio *) asioCallbackInfo->object; try { object->stopStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiAsio: sampleRateChanged() error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_poplog(): return; } EM_log( CK_LOG_SYSTEM, "RtApiAsio: driver reports sample rate changed to %d", (int)sRate ); EM_log( CK_LOG_SYSTEM, "... stream stopped..." ); } long asioMessages(long selector, long value, void* message, double* opt) { long ret = 0; switch(selector) { case kAsioSelectorSupported: if(value == kAsioResetRequest || value == kAsioEngineVersion || value == kAsioResyncRequest || value == kAsioLatenciesChanged // The following three were added for ASIO 2.0, you don't // necessarily have to support them. || value == kAsioSupportsTimeInfo || value == kAsioSupportsTimeCode || value == kAsioSupportsInputMonitor) ret = 1L; break; case kAsioResetRequest: // Defer the task and perform the reset of the driver during the // next "safe" situation. You cannot reset the driver right now, // as this code is called from the driver. Reset the driver is // done by completely destruct is. I.e. ASIOStop(), // ASIODisposeBuffers(), Destruction Afterwards you initialize the // driver again. EM_log( CK_LOG_INFO, "RtApiAsio: driver reset requested!!!" ); ret = 1L; break; case kAsioResyncRequest: // This informs the application that the driver encountered some // non-fatal data loss. It is used for synchronization purposes // of different media. Added mainly to work around the Win16Mutex // problems in Windows 95/98 with the Windows Multimedia system, // which could lose data because the Mutex was held too long by // another thread. However a driver can issue it in other // situations, too. EM_log( CK_LOG_INFO, "RtApiAsio: driver resync requested!!!" ); ret = 1L; break; case kAsioLatenciesChanged: // This will inform the host application that the drivers were // latencies changed. Beware, it this does not mean that the // buffer sizes have changed! You might need to update internal // delay data. EM_log( CK_LOG_INFO, "RtApiAsio: driver latency may have changed!!!" ); ret = 1L; break; case kAsioEngineVersion: // Return the supported ASIO version of the host application. If // a host application does not implement this selector, ASIO 1.0 // is assumed by the driver. ret = 2L; break; case kAsioSupportsTimeInfo: // Informs the driver whether the // asioCallbacks.bufferSwitchTimeInfo() callback is supported. // For compatibility with ASIO 1.0 drivers the host application // should always support the "old" bufferSwitch method, too. ret = 0; break; case kAsioSupportsTimeCode: // Informs the driver wether application is interested in time // code info. If an application does not need to know about time // code, the driver has less work to do. ret = 0; break; } return ret; } bool RtApiAsio :: probeDeviceOpen(int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers) { // For ASIO, a duplex stream MUST use the same driver. if ( mode == INPUT && stream_.mode == OUTPUT && stream_.device[0] != device ) { sprintf(message_, "RtApiAsio: duplex stream must use the same device for input and output."); error(RtError::WARNING); return FAILURE; } // Only load the driver once for duplex stream. ASIOError result; if ( mode != INPUT || stream_.mode != OUTPUT ) { if ( !drivers.loadDriver( (char *)devices_[device].name.c_str() ) ) { sprintf(message_, "RtApiAsio: error loading driver (%s).", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } result = ASIOInit( &driverInfo ); if ( result != ASE_OK ) { sprintf(message_, "RtApiAsio: error (%s) initializing driver (%s).", GetAsioErrorString(result), devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } } // Check the device channel count. long inputChannels, outputChannels; result = ASIOGetChannels( &inputChannels, &outputChannels ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: error (%s) getting input/output channel count (%s).", GetAsioErrorString(result), devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } if ( ( mode == OUTPUT && channels > outputChannels) || ( mode == INPUT && channels > inputChannels) ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) does not support requested channel count (%d).", devices_[device].name.c_str(), channels); error(RtError::DEBUG_WARNING); return FAILURE; } stream_.nDeviceChannels[mode] = channels; stream_.nUserChannels[mode] = channels; // Verify the sample rate is supported. result = ASIOCanSampleRate( (ASIOSampleRate) sampleRate ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) does not support requested sample rate (%d).", devices_[device].name.c_str(), sampleRate); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the sample rate. result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) error setting sample rate (%d).", devices_[device].name.c_str(), sampleRate); error(RtError::DEBUG_WARNING); return FAILURE; } // Determine the driver data type. ASIOChannelInfo channelInfo; channelInfo.channel = 0; if ( mode == OUTPUT ) channelInfo.isInput = false; else channelInfo.isInput = true; result = ASIOGetChannelInfo( &channelInfo ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) error getting data format.", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } // Assuming WINDOWS host is always little-endian. stream_.doByteSwap[mode] = false; stream_.userFormat = format; stream_.deviceFormat[mode] = 0; if ( channelInfo.type == ASIOSTInt16MSB || channelInfo.type == ASIOSTInt16LSB ) { stream_.deviceFormat[mode] = RTAUDIO_SINT16; if ( channelInfo.type == ASIOSTInt16MSB ) stream_.doByteSwap[mode] = true; } else if ( channelInfo.type == ASIOSTInt32MSB || channelInfo.type == ASIOSTInt32LSB ) { stream_.deviceFormat[mode] = RTAUDIO_SINT32; if ( channelInfo.type == ASIOSTInt32MSB ) stream_.doByteSwap[mode] = true; } else if ( channelInfo.type == ASIOSTFloat32MSB || channelInfo.type == ASIOSTFloat32LSB ) { stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; if ( channelInfo.type == ASIOSTFloat32MSB ) stream_.doByteSwap[mode] = true; } else if ( channelInfo.type == ASIOSTFloat64MSB || channelInfo.type == ASIOSTFloat64LSB ) { stream_.deviceFormat[mode] = RTAUDIO_FLOAT64; if ( channelInfo.type == ASIOSTFloat64MSB ) stream_.doByteSwap[mode] = true; } if ( stream_.deviceFormat[mode] == 0 ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: driver (%s) data format not supported by RtAudio.", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the buffer size. For a duplex stream, this will end up // setting the buffer size based on the input constraints, which // should be ok. long minSize, maxSize, preferSize, granularity; result = ASIOGetBufferSize( &minSize, &maxSize, &preferSize, &granularity ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: error (%s) on driver (%s) error getting buffer size.", GetAsioErrorString(result), devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } if ( *bufferSize < minSize ) *bufferSize = minSize; else if ( *bufferSize > maxSize ) *bufferSize = maxSize; else if ( granularity == -1 ) { // Make sure bufferSize is a power of two. double power = log10( (double) *bufferSize ) / log10( 2.0 ); *bufferSize = (int) pow( 2.0, floor(power+0.5) ); if ( *bufferSize < minSize ) *bufferSize = minSize; else if ( *bufferSize > maxSize ) *bufferSize = maxSize; else *bufferSize = preferSize; } else if (granularity != 0) { // to an even multiple of granularity, rounding up. *bufferSize = (*bufferSize + granularity-1)/granularity*granularity; } if ( mode == INPUT && stream_.mode == OUTPUT && stream_.bufferSize != *bufferSize ) std::cerr << "Possible input/output buffersize discrepancy!" << std::endl; stream_.bufferSize = *bufferSize; stream_.nBuffers = 2; // ASIO always uses deinterleaved channels. stream_.deInterleave[mode] = true; // Allocate, if necessary, our AsioHandle structure for the stream. AsioHandle *handle = (AsioHandle *) stream_.apiHandle; if ( handle == 0 ) { handle = (AsioHandle *) calloc(1, sizeof(AsioHandle)); if ( handle == NULL ) { drivers.removeCurrentDriver(); sprintf(message_, "RtApiAsio: error allocating AsioHandle memory (%s).", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } handle->bufferInfos = 0; // Create a manual-reset event. handle->condition = CreateEvent( NULL, // no security TRUE, // manual-reset FALSE, // non-signaled initially NULL ); // unnamed stream_.apiHandle = (void *) handle; } // Create the ASIO internal buffers. Since RtAudio sets up input // and output separately, we'll have to dispose of previously // created output buffers for a duplex stream. if ( mode == INPUT && stream_.mode == OUTPUT ) { ASIODisposeBuffers(); if ( handle->bufferInfos ) free( handle->bufferInfos ); } // Allocate, initialize, and save the bufferInfos in our stream callbackInfo structure. int i, nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; handle->bufferInfos = (ASIOBufferInfo *) malloc( nChannels * sizeof(ASIOBufferInfo) ); if (handle->bufferInfos == NULL) { sprintf(message_, "RtApiAsio: error allocating bufferInfo memory (%s).", devices_[device].name.c_str()); goto error; } ASIOBufferInfo *infos; infos = handle->bufferInfos; for ( i=0; iisInput = ASIOFalse; infos->channelNum = i; infos->buffers[0] = infos->buffers[1] = 0; } for ( i=0; iisInput = ASIOTrue; infos->channelNum = i; infos->buffers[0] = infos->buffers[1] = 0; } // Set up the ASIO callback structure and create the ASIO data buffers. asioCallbacks.bufferSwitch = &bufferSwitch; asioCallbacks.sampleRateDidChange = &sampleRateChanged; asioCallbacks.asioMessage = &asioMessages; asioCallbacks.bufferSwitchTimeInfo = NULL; result = ASIOCreateBuffers( handle->bufferInfos, nChannels, stream_.bufferSize, &asioCallbacks); if ( result != ASE_OK ) { sprintf(message_, "RtApiAsio: eror (%s) on driver (%s) error creating buffers.", GetAsioErrorString(result), devices_[device].name.c_str()); goto error; } // Set flags for buffer conversion. stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] > 1 && stream_.deInterleave[mode]) stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { sprintf(message_, "RtApiAsio: error (%s) allocating user buffer memory (%s).", GetAsioErrorString(result), devices_[device].name.c_str()); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiAsio: error (%s) allocating device buffer memory (%s).", GetAsioErrorString(result), devices_[device].name.c_str()); goto error; } } } stream_.device[mode] = device; stream_.state = STREAM_STOPPED; if ( stream_.mode == OUTPUT && mode == INPUT ) // We had already set up an output stream. stream_.mode = DUPLEX; else stream_.mode = mode; stream_.sampleRate = sampleRate; asioCallbackInfo = &stream_.callbackInfo; stream_.callbackInfo.object = (void *) this; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; kcondition ); if ( handle->bufferInfos ) free( handle->bufferInfos ); free( handle ); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } error(RtError::DEBUG_WARNING); return FAILURE; } void RtApiAsio :: closeStream() { // We don't want an exception to be thrown here because this // function is called by our class destructor. So, do our own // streamId check. if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtApiAsio::closeStream(): no open stream to close!"); error(RtError::WARNING); return; } if (stream_.state == STREAM_RUNNING) ASIOStop(); ASIODisposeBuffers(); drivers.removeCurrentDriver(); AsioHandle *handle = (AsioHandle *) stream_.apiHandle; if ( handle ) { CloseHandle( handle->condition ); if ( handle->bufferInfos ) free( handle->bufferInfos ); free( handle ); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } if (stream_.deviceBuffer) { free(stream_.deviceBuffer); stream_.deviceBuffer = 0; } stream_.mode = UNINITIALIZED; } void RtApiAsio :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); if ( stream_.callbackInfo.usingCallback ) { sprintf(message_, "RtApiAsio: A callback is already set for this stream!"); error(RtError::WARNING); return; } stream_.callbackInfo.callback = (void *) callback; stream_.callbackInfo.userData = userData; stream_.callbackInfo.usingCallback = true; } void RtApiAsio :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; stream_.callbackInfo.userData = NULL; stream_.state = STREAM_STOPPED; stream_.callbackInfo.callback = NULL; MUTEX_UNLOCK(&stream_.mutex); } } void RtApiAsio :: startStream() { verifyStream(); if (stream_.state == STREAM_RUNNING) return; MUTEX_LOCK(&stream_.mutex); ASIOError result = ASIOStart(); if ( result != ASE_OK ) { sprintf(message_, "RtApiAsio: error starting device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } AsioHandle *handle = (AsioHandle *) stream_.apiHandle; handle->stopStream = false; stream_.state = STREAM_RUNNING; MUTEX_UNLOCK(&stream_.mutex); } void RtApiAsio :: stopStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); ASIOError result = ASIOStop(); if ( result != ASE_OK ) { sprintf(message_, "RtApiAsio: error stopping device (%s).", devices_[stream_.device[0]].name.c_str()); MUTEX_UNLOCK(&stream_.mutex); error(RtError::DRIVER_ERROR); } MUTEX_UNLOCK(&stream_.mutex); } void RtApiAsio :: abortStream() { stopStream(); } void RtApiAsio :: tickStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; if (stream_.callbackInfo.usingCallback) { sprintf(message_, "RtApiAsio: tickStream() should not be used when a callback function is set!"); error(RtError::WARNING); return; } AsioHandle *handle = (AsioHandle *) stream_.apiHandle; MUTEX_LOCK(&stream_.mutex); // Release the stream_mutex here and wait for the event // to become signaled by the callback process. MUTEX_UNLOCK(&stream_.mutex); WaitForMultipleObjects(1, &handle->condition, FALSE, INFINITE); ResetEvent( handle->condition ); } void RtApiAsio :: callbackEvent(long bufferIndex) { verifyStream(); if (stream_.state == STREAM_STOPPED) return; CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; AsioHandle *handle = (AsioHandle *) stream_.apiHandle; if ( info->usingCallback && handle->stopStream ) { // Check if the stream should be stopped (via the previous user // callback return value). We stop the stream here, rather than // after the function call, so that output data can first be // processed. this->stopStream(); return; } MUTEX_LOCK(&stream_.mutex); // Invoke user callback first, to get fresh output data. if ( info->usingCallback ) { RtAudioCallback callback = (RtAudioCallback) info->callback; if ( callback(stream_.userBuffer, stream_.bufferSize, info->userData) ) handle->stopStream = true; } int bufferBytes, j; int nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[0]); if (stream_.doConvertBuffer[0]) { convertBuffer( stream_.deviceBuffer, stream_.userBuffer, stream_.convertInfo[0] ); if ( stream_.doByteSwap[0] ) byteSwapBuffer(stream_.deviceBuffer, stream_.bufferSize * stream_.nDeviceChannels[0], stream_.deviceFormat[0]); // Always de-interleave ASIO output data. j = 0; for ( int i=0; ibufferInfos[i].isInput != ASIOTrue ) memcpy(handle->bufferInfos[i].buffers[bufferIndex], &stream_.deviceBuffer[j++*bufferBytes], bufferBytes ); } } else { // single channel only if (stream_.doByteSwap[0]) byteSwapBuffer(stream_.userBuffer, stream_.bufferSize * stream_.nUserChannels[0], stream_.userFormat); for ( int i=0; ibufferInfos[i].isInput != ASIOTrue ) { memcpy(handle->bufferInfos[i].buffers[bufferIndex], stream_.userBuffer, bufferBytes ); break; } } } } if ( stream_.mode == INPUT || stream_.mode == DUPLEX ) { bufferBytes = stream_.bufferSize * formatBytes(stream_.deviceFormat[1]); if (stream_.doConvertBuffer[1]) { // Always interleave ASIO input data. j = 0; for ( int i=0; ibufferInfos[i].isInput == ASIOTrue ) memcpy(&stream_.deviceBuffer[j++*bufferBytes], handle->bufferInfos[i].buffers[bufferIndex], bufferBytes ); } if ( stream_.doByteSwap[1] ) byteSwapBuffer(stream_.deviceBuffer, stream_.bufferSize * stream_.nDeviceChannels[1], stream_.deviceFormat[1]); convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] ); } else { // single channel only for ( int i=0; ibufferInfos[i].isInput == ASIOTrue ) { memcpy(stream_.userBuffer, handle->bufferInfos[i].buffers[bufferIndex], bufferBytes ); break; } } if (stream_.doByteSwap[1]) byteSwapBuffer(stream_.userBuffer, stream_.bufferSize * stream_.nUserChannels[1], stream_.userFormat); } } if ( !info->usingCallback ) SetEvent( handle->condition ); // The following call was suggested by Malte Clasen. While the API // documentation indicates it should not be required, some device // drivers apparently do not function correctly without it. ASIOOutputReady(); MUTEX_UNLOCK(&stream_.mutex); } //******************** End of __WINDOWS_ASIO__ *********************// #endif #if defined(__WINDOWS_DS__) // Windows DirectSound API // chuck #define DIRECTSOUND_VERSION 0x0500 // this #def is here for compatibility with newer DirectSound libs. #include #include #define MINIMUM_DEVICE_BUFFER_SIZE 32768 #ifdef _MSC_VER // if Microsoft Visual C++ #pragma comment(lib,"winmm.lib") // then, auto-link winmm.lib. Otherwise, it has to be added manually. #endif static inline DWORD dsPointerDifference(DWORD laterPointer,DWORD earlierPointer,DWORD bufferSize) { if (laterPointer > earlierPointer) { return laterPointer-earlierPointer; } else { return laterPointer-earlierPointer+bufferSize; } } static inline DWORD dsPointerBetween(DWORD pointer, DWORD laterPointer,DWORD earlierPointer, DWORD bufferSize) { if (pointer > bufferSize) pointer -= bufferSize; if (laterPointer < earlierPointer) { laterPointer += bufferSize; } if (pointer < earlierPointer) { pointer += bufferSize; } return pointer >= earlierPointer && pointer < laterPointer; } #undef GENERATE_DEBUG_LOG // Define this to generate a debug timing log file in c:/rtaudiolog.txt" #ifdef GENERATE_DEBUG_LOG #include "mmsystem.h" #include "fstream" struct TTickRecord { DWORD currentReadPointer, safeReadPointer; DWORD currentWritePointer, safeWritePointer; DWORD readTime, writeTime; DWORD nextWritePointer, nextReadPointer; }; int currentDebugLogEntry = 0; std::vector debugLog(2000); #endif // A structure to hold various information related to the DirectSound // API implementation. struct DsHandle { void *object; void *buffer; UINT bufferPointer; DWORD dsBufferSize; DWORD dsPointerLeadTime; // the number of bytes ahead of the safe pointer to lead by. }; RtApiDs::RtDsStatistics RtApiDs::statistics; // Provides a backdoor hook to monitor for DirectSound read overruns and write underruns. RtApiDs::RtDsStatistics RtApiDs::getDsStatistics() { RtDsStatistics s = statistics; // update the calculated fields. if (s.inputFrameSize != 0) { s.latency += s.readDeviceSafeLeadBytes*1.0/s.inputFrameSize / s.sampleRate; } if (s.outputFrameSize != 0) { s.latency += (s.writeDeviceSafeLeadBytes+ s.writeDeviceBufferLeadBytes)*1.0/s.outputFrameSize / s.sampleRate; } return s; } // Declarations for utility functions, callbacks, and structures // specific to the DirectSound implementation. static bool CALLBACK deviceCountCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext); static bool CALLBACK deviceInfoCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext); static bool CALLBACK defaultDeviceCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext); static bool CALLBACK deviceIdCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext); static char* getErrorString(int code); // chuck #if defined(__WINDOWS_PTHREAD__) extern "C" void * callbackHandler(void * ptr); #else extern "C" unsigned __stdcall callbackHandler(void *ptr); #endif struct enum_info { char name[64]; LPGUID id; bool isInput; bool isValid; }; RtApiDs :: RtApiDs() { // Dsound will run both-threaded. If CoInitialize fails, then just accept whatever the mainline // chose for a threading model. coInitialized = false; HRESULT hr = CoInitialize(NULL); if (!FAILED(hr)) { coInitialized = true; } this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiDs: no Windows DirectSound audio devices found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiDs :: ~RtApiDs() { if (coInitialized) { CoUninitialize(); // balanced call. } if ( stream_.mode != UNINITIALIZED ) closeStream(); } int RtApiDs :: getDefaultInputDevice(void) { enum_info info; info.name[0] = '\0'; // Enumerate through devices to find the default output. HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)defaultDeviceCallback, &info); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Error performing default input device enumeration: %s.", getErrorString(result)); error(RtError::WARNING); return 0; } for ( int i=0; i info(count); for (i=0; iname.c_str(), 64 ); dsinfo.isValid = false; // Enumerate through input devices to find the id (if it exists). HRESULT result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Error performing input device id enumeration: %s.", getErrorString(result)); error(RtError::DEBUG_WARNING); return; } // Do capture probe first. if ( dsinfo.isValid == false ) goto playback_probe; LPDIRECTSOUNDCAPTURE input; result = DirectSoundCaptureCreate( dsinfo.id, &input, NULL ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Could not create capture object (%s): %s.", info->name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); goto playback_probe; } DSCCAPS in_caps; in_caps.dwSize = sizeof(in_caps); result = input->GetCaps( &in_caps ); if ( FAILED(result) ) { input->Release(); sprintf(message_, "RtApiDs: Could not get capture capabilities (%s): %s.", info->name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); goto playback_probe; } // Get input channel information. info->minInputChannels = 1; info->maxInputChannels = in_caps.dwChannels; // Get sample rate and format information. info->sampleRates.clear(); if( in_caps.dwChannels == 2 ) { if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->nativeFormats |= RTAUDIO_SINT8; if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->nativeFormats |= RTAUDIO_SINT8; if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->nativeFormats |= RTAUDIO_SINT8; if ( info->nativeFormats & RTAUDIO_SINT16 ) { if( in_caps.dwFormats & WAVE_FORMAT_1S16 ) info->sampleRates.push_back( 11025 ); if( in_caps.dwFormats & WAVE_FORMAT_2S16 ) info->sampleRates.push_back( 22050 ); if( in_caps.dwFormats & WAVE_FORMAT_4S16 ) info->sampleRates.push_back( 44100 ); } else if ( info->nativeFormats & RTAUDIO_SINT8 ) { if( in_caps.dwFormats & WAVE_FORMAT_1S08 ) info->sampleRates.push_back( 11025 ); if( in_caps.dwFormats & WAVE_FORMAT_2S08 ) info->sampleRates.push_back( 22050 ); if( in_caps.dwFormats & WAVE_FORMAT_4S08 ) info->sampleRates.push_back( 44100 ); } } else if ( in_caps.dwChannels == 1 ) { if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->nativeFormats |= RTAUDIO_SINT16; if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->nativeFormats |= RTAUDIO_SINT8; if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->nativeFormats |= RTAUDIO_SINT8; if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->nativeFormats |= RTAUDIO_SINT8; if ( info->nativeFormats & RTAUDIO_SINT16 ) { if( in_caps.dwFormats & WAVE_FORMAT_1M16 ) info->sampleRates.push_back( 11025 ); if( in_caps.dwFormats & WAVE_FORMAT_2M16 ) info->sampleRates.push_back( 22050 ); if( in_caps.dwFormats & WAVE_FORMAT_4M16 ) info->sampleRates.push_back( 44100 ); } else if ( info->nativeFormats & RTAUDIO_SINT8 ) { if( in_caps.dwFormats & WAVE_FORMAT_1M08 ) info->sampleRates.push_back( 11025 ); if( in_caps.dwFormats & WAVE_FORMAT_2M08 ) info->sampleRates.push_back( 22050 ); if( in_caps.dwFormats & WAVE_FORMAT_4M08 ) info->sampleRates.push_back( 44100 ); } } else info->minInputChannels = 0; // technically, this would be an error input->Release(); playback_probe: dsinfo.isValid = false; // Enumerate through output devices to find the id (if it exists). result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Error performing output device id enumeration: %s.", getErrorString(result)); error(RtError::DEBUG_WARNING); return; } // Now do playback probe. if ( dsinfo.isValid == false ) goto check_parameters; LPDIRECTSOUND output; DSCAPS out_caps; result = DirectSoundCreate( dsinfo.id, &output, NULL ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Could not create playback object (%s): %s.", info->name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); goto check_parameters; } out_caps.dwSize = sizeof(out_caps); result = output->GetCaps( &out_caps ); if ( FAILED(result) ) { output->Release(); sprintf(message_, "RtApiDs: Could not get playback capabilities (%s): %s.", info->name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); goto check_parameters; } // Get output channel information. info->minOutputChannels = 1; info->maxOutputChannels = ( out_caps.dwFlags & DSCAPS_PRIMARYSTEREO ) ? 2 : 1; // Get sample rate information. Use capture device rate information // if it exists. if ( info->sampleRates.size() == 0 ) { info->sampleRates.push_back( (int) out_caps.dwMinSecondarySampleRate ); if ( out_caps.dwMaxSecondarySampleRate > out_caps.dwMinSecondarySampleRate ) info->sampleRates.push_back( (int) out_caps.dwMaxSecondarySampleRate ); } else { // Check input rates against output rate range. If there's an // inconsistency (such as a duplex-capable device which reports a // single output rate of 48000 Hz), we'll go with the output // rate(s) since the DirectSoundCapture API is stupid and broken. // Note that the probed sample rate values are NOT used when // opening the device. Thanks to Tue Andersen for reporting this. if ( info->sampleRates.back() < (int) out_caps.dwMinSecondarySampleRate ) { info->sampleRates.clear(); info->sampleRates.push_back( (int) out_caps.dwMinSecondarySampleRate ); if ( out_caps.dwMaxSecondarySampleRate > out_caps.dwMinSecondarySampleRate ) info->sampleRates.push_back( (int) out_caps.dwMaxSecondarySampleRate ); } else { for ( int i=info->sampleRates.size()-1; i>=0; i-- ) { if ( (unsigned int) info->sampleRates[i] > out_caps.dwMaxSecondarySampleRate ) info->sampleRates.erase( info->sampleRates.begin() + i ); } while ( info->sampleRates.size() > 0 && ((unsigned int) info->sampleRates[0] < out_caps.dwMinSecondarySampleRate) ) { info->sampleRates.erase( info->sampleRates.begin() ); } } } // Get format information. if ( out_caps.dwFlags & DSCAPS_PRIMARY16BIT ) info->nativeFormats |= RTAUDIO_SINT16; if ( out_caps.dwFlags & DSCAPS_PRIMARY8BIT ) info->nativeFormats |= RTAUDIO_SINT8; output->Release(); check_parameters: if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 ) { sprintf(message_, "RtApiDs: no reported input or output channels for device (%s).", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } if ( info->sampleRates.size() == 0 || info->nativeFormats == 0 ) { sprintf(message_, "RtApiDs: no reported sample rates or data formats for device (%s).", info->name.c_str()); error(RtError::DEBUG_WARNING); return; } // Determine duplex status. if (info->maxInputChannels < info->maxOutputChannels) info->maxDuplexChannels = info->maxInputChannels; else info->maxDuplexChannels = info->maxOutputChannels; if (info->minInputChannels < info->minOutputChannels) info->minDuplexChannels = info->minInputChannels; else info->minDuplexChannels = info->minOutputChannels; if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true; else info->hasDuplexSupport = false; info->probed = true; return; } bool RtApiDs :: probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers) { HRESULT result; HWND hWnd = GetForegroundWindow(); // According to a note in PortAudio, using GetDesktopWindow() // instead of GetForegroundWindow() is supposed to avoid problems // that occur when the application's window is not the foreground // window. Also, if the application window closes before the // DirectSound buffer, DirectSound can crash. However, for console // applications, no sound was produced when using GetDesktopWindow(). long buffer_size; LPVOID audioPtr; DWORD dataLen; int nBuffers; // Check the numberOfBuffers parameter and limit the lowest value to // two. This is a judgement call and a value of two is probably too // low for capture, but it should work for playback. if (numberOfBuffers < 2) nBuffers = 2; else nBuffers = numberOfBuffers; // Define the wave format structure (16-bit PCM, srate, channels) WAVEFORMATEX waveFormat; ZeroMemory(&waveFormat, sizeof(WAVEFORMATEX)); waveFormat.wFormatTag = WAVE_FORMAT_PCM; waveFormat.nChannels = channels; waveFormat.nSamplesPerSec = (unsigned long) sampleRate; // Determine the data format. if ( devices_[device].nativeFormats ) { // 8-bit and/or 16-bit support if ( format == RTAUDIO_SINT8 ) { if ( devices_[device].nativeFormats & RTAUDIO_SINT8 ) waveFormat.wBitsPerSample = 8; else waveFormat.wBitsPerSample = 16; } else { if ( devices_[device].nativeFormats & RTAUDIO_SINT16 ) waveFormat.wBitsPerSample = 16; else waveFormat.wBitsPerSample = 8; } } else { sprintf(message_, "RtApiDs: no reported data formats for device (%s).", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } waveFormat.nBlockAlign = waveFormat.nChannels * waveFormat.wBitsPerSample / 8; waveFormat.nAvgBytesPerSec = waveFormat.nSamplesPerSec * waveFormat.nBlockAlign; // Determine the device buffer size. By default, 32k, // but we will grow it to make allowances for very large softare buffer sizes. DWORD dsBufferSize = 0; DWORD dsPointerLeadTime = 0; buffer_size = MINIMUM_DEVICE_BUFFER_SIZE; // sound cards will always *knock wood* support this // poisonously large buffer lead time? Then increase the device buffer size accordingly. while (dsPointerLeadTime *2U > (DWORD)buffer_size) { buffer_size *= 2; } enum_info dsinfo; void *ohandle = 0, *bhandle = 0; strncpy( dsinfo.name, devices_[device].name.c_str(), 64 ); dsinfo.isValid = false; if ( mode == OUTPUT ) { dsPointerLeadTime = (numberOfBuffers) * (*bufferSize) * (waveFormat.wBitsPerSample / 8) *channels; if ( devices_[device].maxOutputChannels < channels ) { sprintf(message_, "RtApiDs: requested channels (%d) > than supported (%d) by device (%s).", channels, devices_[device].maxOutputChannels, devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } // Enumerate through output devices to find the id (if it exists). result = DirectSoundEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Error performing output device id enumeration: %s.", getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } if ( dsinfo.isValid == false ) { sprintf(message_, "RtApiDs: output device (%s) id not found!", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } LPGUID id = dsinfo.id; LPDIRECTSOUND object; LPDIRECTSOUNDBUFFER buffer; DSBUFFERDESC bufferDescription; result = DirectSoundCreate( id, &object, NULL ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Could not create playback object (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Set cooperative level to DSSCL_EXCLUSIVE result = object->SetCooperativeLevel(hWnd, DSSCL_EXCLUSIVE); if ( FAILED(result) ) { object->Release(); sprintf(message_, "RtApiDs: Unable to set cooperative level (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Even though we will write to the secondary buffer, we need to // access the primary buffer to set the correct output format // (since the default is 8-bit, 22 kHz!). Setup the DS primary // buffer description. ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC)); bufferDescription.dwSize = sizeof(DSBUFFERDESC); bufferDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; // Obtain the primary buffer result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL); if ( FAILED(result) ) { object->Release(); sprintf(message_, "RtApiDs: Unable to access primary buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the primary DS buffer sound format. result = buffer->SetFormat(&waveFormat); if ( FAILED(result) ) { object->Release(); sprintf(message_, "RtApiDs: Unable to set primary buffer format (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Setup the secondary DS buffer description. dsBufferSize = (DWORD)buffer_size; ZeroMemory(&bufferDescription, sizeof(DSBUFFERDESC)); bufferDescription.dwSize = sizeof(DSBUFFERDESC); bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCHARDWARE ); // Force hardware mixing bufferDescription.dwBufferBytes = buffer_size; bufferDescription.lpwfxFormat = &waveFormat; // Try to create the secondary DS buffer. If that doesn't work, // try to use software mixing. Otherwise, there's a problem. result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL); if ( FAILED(result) ) { bufferDescription.dwFlags = ( DSBCAPS_STICKYFOCUS | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_LOCSOFTWARE ); // Force software mixing result = object->CreateSoundBuffer(&bufferDescription, &buffer, NULL); if ( FAILED(result) ) { object->Release(); sprintf(message_, "RtApiDs: Unable to create secondary DS buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } } // Get the buffer size ... might be different from what we specified. DSBCAPS dsbcaps; dsbcaps.dwSize = sizeof(DSBCAPS); buffer->GetCaps(&dsbcaps); buffer_size = dsbcaps.dwBufferBytes; // Lock the DS buffer result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0); if ( FAILED(result) ) { object->Release(); buffer->Release(); sprintf(message_, "RtApiDs: Unable to lock buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Zero the DS buffer ZeroMemory(audioPtr, dataLen); // Unlock the DS buffer result = buffer->Unlock(audioPtr, dataLen, NULL, 0); if ( FAILED(result) ) { object->Release(); buffer->Release(); sprintf(message_, "RtApiDs: Unable to unlock buffer(%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } ohandle = (void *) object; bhandle = (void *) buffer; stream_.nDeviceChannels[0] = channels; } if ( mode == INPUT ) { if ( devices_[device].maxInputChannels < channels ) { sprintf(message_, "RtAudioDS: device (%s) does not support %d channels.", devices_[device].name.c_str(), channels); error(RtError::DEBUG_WARNING); return FAILURE; } // Enumerate through input devices to find the id (if it exists). result = DirectSoundCaptureEnumerate((LPDSENUMCALLBACK)deviceIdCallback, &dsinfo); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Error performing input device id enumeration: %s.", getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } if ( dsinfo.isValid == false ) { sprintf(message_, "RtAudioDS: input device (%s) id not found!", devices_[device].name.c_str()); error(RtError::DEBUG_WARNING); return FAILURE; } LPGUID id = dsinfo.id; LPDIRECTSOUNDCAPTURE object; LPDIRECTSOUNDCAPTUREBUFFER buffer; DSCBUFFERDESC bufferDescription; result = DirectSoundCaptureCreate( id, &object, NULL ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Could not create capture object (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Setup the secondary DS buffer description. dsBufferSize = buffer_size; ZeroMemory(&bufferDescription, sizeof(DSCBUFFERDESC)); bufferDescription.dwSize = sizeof(DSCBUFFERDESC); bufferDescription.dwFlags = 0; bufferDescription.dwReserved = 0; bufferDescription.dwBufferBytes = buffer_size; bufferDescription.lpwfxFormat = &waveFormat; // Create the capture buffer. result = object->CreateCaptureBuffer(&bufferDescription, &buffer, NULL); if ( FAILED(result) ) { object->Release(); sprintf(message_, "RtApiDs: Unable to create capture buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Lock the capture buffer result = buffer->Lock(0, buffer_size, &audioPtr, &dataLen, NULL, NULL, 0); if ( FAILED(result) ) { object->Release(); buffer->Release(); sprintf(message_, "RtApiDs: Unable to lock capture buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } // Zero the buffer ZeroMemory(audioPtr, dataLen); // Unlock the buffer result = buffer->Unlock(audioPtr, dataLen, NULL, 0); if ( FAILED(result) ) { object->Release(); buffer->Release(); sprintf(message_, "RtApiDs: Unable to unlock capture buffer (%s): %s.", devices_[device].name.c_str(), getErrorString(result)); error(RtError::DEBUG_WARNING); return FAILURE; } ohandle = (void *) object; bhandle = (void *) buffer; stream_.nDeviceChannels[1] = channels; } stream_.userFormat = format; if ( waveFormat.wBitsPerSample == 8 ) stream_.deviceFormat[mode] = RTAUDIO_SINT8; else stream_.deviceFormat[mode] = RTAUDIO_SINT16; stream_.nUserChannels[mode] = channels; stream_.bufferSize = *bufferSize; // Set flags for buffer conversion stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; if (stream_.nUserChannels[mode] < stream_.nDeviceChannels[mode]) stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { sprintf(message_, "RtApiDs: error allocating user buffer memory (%s).", devices_[device].name.c_str()); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiDs: error allocating device buffer memory (%s).", devices_[device].name.c_str()); goto error; } } } // Allocate our DsHandle structures for the stream. DsHandle *handles; if ( stream_.apiHandle == 0 ) { handles = (DsHandle *) calloc(2, sizeof(DsHandle)); if ( handles == NULL ) { sprintf(message_, "RtApiDs: Error allocating DsHandle memory (%s).", devices_[device].name.c_str()); goto error; } handles[0].object = 0; handles[1].object = 0; stream_.apiHandle = (void *) handles; } else handles = (DsHandle *) stream_.apiHandle; handles[mode].object = ohandle; handles[mode].buffer = bhandle; handles[mode].dsBufferSize = dsBufferSize; handles[mode].dsPointerLeadTime = dsPointerLeadTime; stream_.device[mode] = device; stream_.state = STREAM_STOPPED; if ( stream_.mode == OUTPUT && mode == INPUT ) // We had already set up an output stream. stream_.mode = DUPLEX; else stream_.mode = mode; stream_.nBuffers = nBuffers; stream_.sampleRate = sampleRate; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; kRelease(); object->Release(); } if (handles[1].object) { LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handles[1].object; LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; if (buffer) buffer->Release(); object->Release(); } free(handles); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } error(RtError::DEBUG_WARNING); return FAILURE; } void RtApiDs :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; if ( info->usingCallback ) { sprintf(message_, "RtApiDs: A callback is already set for this stream!"); error(RtError::WARNING); return; } info->callback = (void *) callback; info->userData = userData; info->usingCallback = true; info->object = (void *) this; // chuck #if defined(__WINDOWS_PTHREAD__) pthread_attr_t attr; pthread_attr_init(&attr); // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // pthread_attr_setschedpolicy(&attr, SCHED_RR); int err = pthread_create(&info->thread, &attr, callbackHandler, &stream_.callbackInfo); pthread_attr_destroy(&attr); if (err) { info->usingCallback = false; sprintf(message_, "RtApiDs: error starting callback thread!"); error(RtError::THREAD_ERROR); } #else unsigned thread_id; info->thread = _beginthreadex(NULL, 0, &callbackHandler, &stream_.callbackInfo, 0, &thread_id); if (info->thread == 0) { info->usingCallback = false; sprintf(message_, "RtApiDs: error starting callback thread!"); error(RtError::THREAD_ERROR); } #endif // When spawning multiple threads in quick succession, it appears to be // necessary to wait a bit for each to initialize ... another windoism! Sleep(1); } void RtApiDs :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; WaitForSingleObject( (HANDLE)stream_.callbackInfo.thread, INFINITE ); CloseHandle( (HANDLE)stream_.callbackInfo.thread ); stream_.callbackInfo.thread = 0; stream_.callbackInfo.callback = NULL; stream_.callbackInfo.userData = NULL; MUTEX_UNLOCK(&stream_.mutex); } } void RtApiDs :: closeStream() { // We don't want an exception to be thrown here because this // function is called by our class destructor. So, do our own // streamId check. if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtApiDs::closeStream(): no open stream to close!"); error(RtError::WARNING); return; } if (stream_.callbackInfo.usingCallback) { stream_.callbackInfo.usingCallback = false; WaitForSingleObject( (HANDLE)stream_.callbackInfo.thread, INFINITE ); CloseHandle( (HANDLE)stream_.callbackInfo.thread ); } DsHandle *handles = (DsHandle *) stream_.apiHandle; if (handles) { if (handles[0].object) { LPDIRECTSOUND object = (LPDIRECTSOUND) handles[0].object; LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; if (buffer) { buffer->Stop(); buffer->Release(); } object->Release(); } if (handles[1].object) { LPDIRECTSOUNDCAPTURE object = (LPDIRECTSOUNDCAPTURE) handles[1].object; LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; if (buffer) { buffer->Stop(); buffer->Release(); } object->Release(); } free(handles); stream_.apiHandle = 0; } if (stream_.userBuffer) { free(stream_.userBuffer); stream_.userBuffer = 0; } if (stream_.deviceBuffer) { free(stream_.deviceBuffer); stream_.deviceBuffer = 0; } stream_.mode = UNINITIALIZED; } void RtApiDs :: startStream() { verifyStream(); if (stream_.state == STREAM_RUNNING) return; // increase scheduler frequency on lesser windows (a side-effect of increasing timer accuracy. // on greater windows (Win2K or later), this is already in effect. MUTEX_LOCK(&stream_.mutex); DsHandle *handles = (DsHandle *) stream_.apiHandle; timeBeginPeriod(1); memset(&statistics,0,sizeof(statistics)); statistics.sampleRate = stream_.sampleRate; statistics.writeDeviceBufferLeadBytes = handles[0].dsPointerLeadTime ; buffersRolling = false; duplexPrerollBytes = 0; if (stream_.mode == DUPLEX) { // 0.5 seconds of silence in DUPLEX mode while the devices spin up and synchronize. duplexPrerollBytes = (int)(0.5*stream_.sampleRate*formatBytes( stream_.deviceFormat[1])*stream_.nDeviceChannels[1]); } #ifdef GENERATE_DEBUG_LOG currentDebugLogEntry = 0; #endif HRESULT result; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { statistics.outputFrameSize = formatBytes( stream_.deviceFormat[0]) *stream_.nDeviceChannels[0]; LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; result = buffer->Play(0, 0, DSBPLAY_LOOPING ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to start buffer (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { statistics.inputFrameSize = formatBytes( stream_.deviceFormat[1]) *stream_.nDeviceChannels[1]; LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; result = buffer->Start(DSCBSTART_LOOPING ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to start capture buffer (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } } stream_.state = STREAM_RUNNING; MUTEX_UNLOCK(&stream_.mutex); } void RtApiDs :: stopStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); timeEndPeriod(1); // revert to normal scheduler frequency on lesser windows. #ifdef GENERATE_DEBUG_LOG // write the timing log to a .TSV file for analysis in Excel. unlink("c:/rtaudiolog.txt"); std::ofstream os("c:/rtaudiolog.txt"); os << "writeTime\treadDelay\tnextWritePointer\tnextReadPointer\tcurrentWritePointer\tsafeWritePointer\tcurrentReadPointer\tsafeReadPointer" << std::endl; for (int i = 0; i < currentDebugLogEntry ; ++i) { TTickRecord &r = debugLog[i]; os << r.writeTime-debugLog[0].writeTime << "\t" << (r.readTime-r.writeTime) << "\t" << r.nextWritePointer % BUFFER_SIZE << "\t" << r.nextReadPointer % BUFFER_SIZE << "\t" << r.currentWritePointer % BUFFER_SIZE << "\t" << r.safeWritePointer % BUFFER_SIZE << "\t" << r.currentReadPointer % BUFFER_SIZE << "\t" << r.safeReadPointer % BUFFER_SIZE << std::endl; } #endif // There is no specific DirectSound API call to "drain" a buffer // before stopping. We can hack this for playback by writing zeroes // for another bufferSize * nBuffers frames. For capture, the // concept is less clear so we'll repeat what we do in the // abortStream() case. HRESULT result; DWORD dsBufferSize; LPVOID buffer1 = NULL; LPVOID buffer2 = NULL; DWORD bufferSize1 = 0; DWORD bufferSize2 = 0; DsHandle *handles = (DsHandle *) stream_.apiHandle; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { DWORD currentPos, safePos; long buffer_bytes = stream_.bufferSize * stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; long nextWritePos = handles[0].bufferPointer; dsBufferSize = handles[0].dsBufferSize; // Write zeroes for nBuffer counts. for (int i=0; iGetCurrentPosition(¤tPos, &safePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // Chase nextWritePos. if ( currentPos < (DWORD)nextWritePos ) currentPos += dsBufferSize; // unwrap offset DWORD endWrite = nextWritePos + buffer_bytes; // Check whether the entire write region is behind the play pointer. while ( currentPos < endWrite ) { double millis = (endWrite - currentPos) * 900.0; millis /= ( formatBytes(stream_.deviceFormat[0]) * stream_.nDeviceChannels[0] *stream_.sampleRate); if ( millis < 1.0 ) millis = 1.0; Sleep( (DWORD) millis ); // Wake up, find out where we are now result = dsBuffer->GetCurrentPosition( ¤tPos, &safePos ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if ( currentPos < (DWORD)nextWritePos ) currentPos += dsBufferSize; // unwrap offset } // Lock free space in the buffer result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1, &bufferSize1, &buffer2, &bufferSize2, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock buffer during playback (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR, TRUE); } // Zero the free space ZeroMemory(buffer1, bufferSize1); if (buffer2 != NULL) ZeroMemory(buffer2, bufferSize2); // Update our buffer offset and unlock sound buffer dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock buffer during playback (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize; handles[0].bufferPointer = nextWritePos; } // If we play again, start at the beginning of the buffer. handles[0].bufferPointer = 0; } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; buffer1 = NULL; bufferSize1 = 0; result = buffer->Stop(); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to stop capture buffer (%s): %s", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } dsBufferSize = handles[1].dsBufferSize; // Lock the buffer and clear it so that if we start to play again, // we won't have old data playing. result = buffer->Lock(0, dsBufferSize, &buffer1, &bufferSize1, NULL, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock capture buffer (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // Zero the DS buffer ZeroMemory(buffer1, bufferSize1); // Unlock the DS buffer result = buffer->Unlock(buffer1, bufferSize1, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock capture buffer (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // If we start recording again, we must begin at beginning of buffer. handles[1].bufferPointer = 0; } MUTEX_UNLOCK(&stream_.mutex); } void RtApiDs :: abortStream() { verifyStream(); if (stream_.state == STREAM_STOPPED) return; // Change the state before the lock to improve shutdown response // when using a callback. stream_.state = STREAM_STOPPED; MUTEX_LOCK(&stream_.mutex); HRESULT result; long dsBufferSize; LPVOID audioPtr; DWORD dataLen; DsHandle *handles = (DsHandle *) stream_.apiHandle; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { LPDIRECTSOUNDBUFFER buffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; result = buffer->Stop(); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to stop buffer (%s): %s", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } dsBufferSize = handles[0].dsBufferSize; // Lock the buffer and clear it so that if we start to play again, // we won't have old data playing. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock buffer (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // Zero the DS buffer ZeroMemory(audioPtr, dataLen); // Unlock the DS buffer result = buffer->Unlock(audioPtr, dataLen, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock buffer (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // If we start playing again, we must begin at beginning of buffer. handles[0].bufferPointer = 0; } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { LPDIRECTSOUNDCAPTUREBUFFER buffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; audioPtr = NULL; dataLen = 0; result = buffer->Stop(); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to stop capture buffer (%s): %s", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } dsBufferSize = handles[1].dsBufferSize; // Lock the buffer and clear it so that if we start to play again, // we won't have old data playing. result = buffer->Lock(0, dsBufferSize, &audioPtr, &dataLen, NULL, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock capture buffer (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // Zero the DS buffer ZeroMemory(audioPtr, dataLen); // Unlock the DS buffer result = buffer->Unlock(audioPtr, dataLen, NULL, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock capture buffer (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } // If we start recording again, we must begin at beginning of buffer. handles[1].bufferPointer = 0; } MUTEX_UNLOCK(&stream_.mutex); } int RtApiDs :: streamWillBlock() { verifyStream(); if (stream_.state == STREAM_STOPPED) return 0; MUTEX_LOCK(&stream_.mutex); int channels; int frames = 0; HRESULT result; DWORD currentPos, safePos; channels = 1; DsHandle *handles = (DsHandle *) stream_.apiHandle; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; UINT nextWritePos = handles[0].bufferPointer; channels = stream_.nDeviceChannels[0]; DWORD dsBufferSize = handles[0].dsBufferSize; // Find out where the read and "safe write" pointers are. result = dsBuffer->GetCurrentPosition(¤tPos, &safePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } DWORD leadPos = safePos + handles[0].dsPointerLeadTime; if (leadPos > dsBufferSize) { leadPos -= dsBufferSize; } if ( leadPos < nextWritePos ) leadPos += dsBufferSize; // unwrap offset frames = (leadPos - nextWritePos); frames /= channels * formatBytes(stream_.deviceFormat[0]); } if (stream_.mode == INPUT ) { // note that we don't block on DUPLEX input anymore. We run lockstep with the write pointer instead. LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; UINT nextReadPos = handles[1].bufferPointer; channels = stream_.nDeviceChannels[1]; DWORD dsBufferSize = handles[1].dsBufferSize; // Find out where the write and "safe read" pointers are. result = dsBuffer->GetCurrentPosition(¤tPos, &safePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if ( safePos < (DWORD)nextReadPos ) safePos += dsBufferSize; // unwrap offset frames = (int)(safePos - nextReadPos); frames /= channels * formatBytes(stream_.deviceFormat[1]); } frames = stream_.bufferSize - frames; if (frames < 0) frames = 0; MUTEX_UNLOCK(&stream_.mutex); return frames; } void RtApiDs :: tickStream() { verifyStream(); int stopStream = 0; if (stream_.state == STREAM_STOPPED) { if (stream_.callbackInfo.usingCallback) Sleep(50); // sleep 50 milliseconds return; } else if (stream_.callbackInfo.usingCallback) { RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; stopStream = callback(stream_.userBuffer, stream_.bufferSize, stream_.callbackInfo.userData); } MUTEX_LOCK(&stream_.mutex); // The state might change while waiting on a mutex. if (stream_.state == STREAM_STOPPED) { MUTEX_UNLOCK(&stream_.mutex); return; } HRESULT result; DWORD currentWritePos, safeWritePos; DWORD currentReadPos, safeReadPos; DWORD leadPos; UINT nextWritePos; #ifdef GENERATE_DEBUG_LOG DWORD writeTime, readTime; #endif LPVOID buffer1 = NULL; LPVOID buffer2 = NULL; DWORD bufferSize1 = 0; DWORD bufferSize2 = 0; char *buffer; long buffer_bytes; DsHandle *handles = (DsHandle *) stream_.apiHandle; if (stream_.mode == DUPLEX && !buffersRolling) { assert(handles[0].dsBufferSize == handles[1].dsBufferSize); // it takes a while for the devices to get rolling. As a result, there's // no guarantee that the capture and write device pointers will move in lockstep. // Wait here for both devices to start rolling, and then set our buffer pointers accordingly. // e.g. Crystal Drivers: the capture buffer starts up 5700 to 9600 bytes later than the write // buffer. // Stub: a serious risk of having a pre-emptive scheduling round take place between // the two GetCurrentPosition calls... but I'm really not sure how to solve the problem. // Temporarily boost to Realtime priority, maybe; but I'm not sure what priority the // directsound service threads run at. We *should* be roughly within a ms or so of correct. LPDIRECTSOUNDBUFFER dsWriteBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; LPDIRECTSOUNDCAPTUREBUFFER dsCaptureBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; DWORD initialWritePos, initialSafeWritePos; DWORD initialReadPos, initialSafeReadPos;; result = dsWriteBuffer->GetCurrentPosition(&initialWritePos, &initialSafeWritePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } result = dsCaptureBuffer->GetCurrentPosition(&initialReadPos, &initialSafeReadPos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } while (true) { result = dsWriteBuffer->GetCurrentPosition(¤tWritePos, &safeWritePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } result = dsCaptureBuffer->GetCurrentPosition(¤tReadPos, &safeReadPos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if (safeWritePos != initialSafeWritePos && safeReadPos != initialSafeReadPos) { break; } Sleep(1); } assert(handles[0].dsBufferSize == handles[1].dsBufferSize); UINT writeBufferLead = (safeWritePos-safeReadPos + handles[0].dsBufferSize) % handles[0].dsBufferSize; buffersRolling = true; handles[0].bufferPointer = (safeWritePos + handles[0].dsPointerLeadTime); handles[1].bufferPointer = safeReadPos; } if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { LPDIRECTSOUNDBUFFER dsBuffer = (LPDIRECTSOUNDBUFFER) handles[0].buffer; // Setup parameters and do buffer conversion if necessary. if (stream_.doConvertBuffer[0]) { buffer = stream_.deviceBuffer; convertBuffer( buffer, stream_.userBuffer, stream_.convertInfo[0] ); buffer_bytes = stream_.bufferSize * stream_.nDeviceChannels[0]; buffer_bytes *= formatBytes(stream_.deviceFormat[0]); } else { buffer = stream_.userBuffer; buffer_bytes = stream_.bufferSize * stream_.nUserChannels[0]; buffer_bytes *= formatBytes(stream_.userFormat); } // No byte swapping necessary in DirectSound implementation. // Ahhh ... windoze. 16-bit data is signed but 8-bit data is // unsigned. So, we need to convert our signed 8-bit data here to // unsigned. if ( stream_.deviceFormat[0] == RTAUDIO_SINT8 ) for ( int i=0; iGetCurrentPosition(¤tWritePos, &safeWritePos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current position (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } leadPos = safeWritePos + handles[0].dsPointerLeadTime; if (leadPos > dsBufferSize) { leadPos -= dsBufferSize; } if ( leadPos < nextWritePos ) leadPos += dsBufferSize; // unwrap offset endWrite = nextWritePos + buffer_bytes; // Check whether the entire write region is behind the play pointer. if ( leadPos >= endWrite ) break; // If we are here, then we must wait until the play pointer gets // beyond the write region. The approach here is to use the // Sleep() function to suspend operation until safePos catches // up. Calculate number of milliseconds to wait as: // time = distance * (milliseconds/second) * fudgefactor / // ((bytes/sample) * (samples/second)) // A "fudgefactor" less than 1 is used because it was found // that sleeping too long was MUCH worse than sleeping for // several shorter periods. double millis = (endWrite - leadPos) * 900.0; millis /= ( formatBytes(stream_.deviceFormat[0]) *stream_.nDeviceChannels[0]* stream_.sampleRate); if ( millis < 1.0 ) millis = 1.0; if (millis > 50.0) { static int nOverruns = 0; ++nOverruns; } Sleep( (DWORD) millis ); // Sleep( (DWORD) 2); } #ifdef GENERATE_DEBUG_LOG writeTime = timeGetTime(); #endif if (statistics.writeDeviceSafeLeadBytes < dsPointerDifference(safeWritePos,currentWritePos,handles[0].dsBufferSize)) { statistics.writeDeviceSafeLeadBytes = dsPointerDifference(safeWritePos,currentWritePos,handles[0].dsBufferSize); } if ( dsPointerBetween(nextWritePos,safeWritePos,currentWritePos,dsBufferSize) || dsPointerBetween(endWrite,safeWritePos,currentWritePos,dsBufferSize) ) { // we've strayed into the forbidden zone. // resync the read pointer. ++statistics.numberOfWriteUnderruns; nextWritePos = safeWritePos + handles[0].dsPointerLeadTime-buffer_bytes+dsBufferSize; while (nextWritePos >= dsBufferSize) nextWritePos-= dsBufferSize; handles[0].bufferPointer = nextWritePos; endWrite = nextWritePos + buffer_bytes; } // Lock free space in the buffer result = dsBuffer->Lock (nextWritePos, buffer_bytes, &buffer1, &bufferSize1, &buffer2, &bufferSize2, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock buffer during playback (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR, TRUE); } // Copy our buffer into the DS buffer CopyMemory(buffer1, buffer, bufferSize1); if (buffer2 != NULL) CopyMemory(buffer2, buffer+bufferSize1, bufferSize2); // Update our buffer offset and unlock sound buffer dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock buffer during playback (%s): %s.", devices_[stream_.device[0]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } nextWritePos = (nextWritePos + bufferSize1 + bufferSize2) % dsBufferSize; handles[0].bufferPointer = nextWritePos; } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { // Setup parameters. if (stream_.doConvertBuffer[1]) { buffer = stream_.deviceBuffer; buffer_bytes = stream_.bufferSize * stream_.nDeviceChannels[1]; buffer_bytes *= formatBytes(stream_.deviceFormat[1]); } else { buffer = stream_.userBuffer; buffer_bytes = stream_.bufferSize * stream_.nUserChannels[1]; buffer_bytes *= formatBytes(stream_.userFormat); } LPDIRECTSOUNDCAPTUREBUFFER dsBuffer = (LPDIRECTSOUNDCAPTUREBUFFER) handles[1].buffer; long nextReadPos = handles[1].bufferPointer; DWORD dsBufferSize = handles[1].dsBufferSize; // Find out where the write and "safe read" pointers are. result = dsBuffer->GetCurrentPosition(¤tReadPos, &safeReadPos); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if ( safeReadPos < (DWORD)nextReadPos ) safeReadPos += dsBufferSize; // unwrap offset DWORD endRead = nextReadPos + buffer_bytes; // Handling depends on whether we are INPUT or DUPLEX. // If we're in INPUT mode then waiting is a good thing. If we're in DUPLEX mode, // then a wait here will drag the write pointers into the forbidden zone. // // In DUPLEX mode, rather than wait, we will back off the read pointer until // it's in a safe position. This causes dropouts, but it seems to be the only // practical way to sync up the read and write pointers reliably, given the // the very complex relationship between phase and increment of the read and write // pointers. // // In order to minimize audible dropouts in DUPLEX mode, we will provide a pre-roll // period of 0.5 seconds // in which we return zeros from the read buffer while the pointers sync up. if (stream_.mode == DUPLEX) { if (safeReadPos < endRead) { if (duplexPrerollBytes <= 0) { // pre-roll time over. Be more agressive. int adjustment = endRead-safeReadPos; ++statistics.numberOfReadOverruns; // Two cases: // large adjustments: we've probably run out of CPU cycles, so just resync exactly, // and perform fine adjustments later. // small adjustments: back off by twice as much. if (adjustment >= 2*buffer_bytes) { nextReadPos = safeReadPos-2*buffer_bytes; } else { nextReadPos = safeReadPos-buffer_bytes-adjustment; } statistics.readDeviceSafeLeadBytes = currentReadPos-nextReadPos; if (statistics.readDeviceSafeLeadBytes < 0) statistics.readDeviceSafeLeadBytes += dsBufferSize; if (nextReadPos < 0) nextReadPos += dsBufferSize; } else { // in pre=roll time. Just do it. nextReadPos = safeReadPos-buffer_bytes; while (nextReadPos < 0) nextReadPos += dsBufferSize; } endRead = nextReadPos + buffer_bytes; } } else { while ( safeReadPos < endRead ) { // See comments for playback. double millis = (endRead - safeReadPos) * 900.0; millis /= ( formatBytes(stream_.deviceFormat[1]) * stream_.nDeviceChannels[1] * stream_.sampleRate); if ( millis < 1.0 ) millis = 1.0; Sleep( (DWORD) millis ); // Wake up, find out where we are now result = dsBuffer->GetCurrentPosition( ¤tReadPos, &safeReadPos ); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to get current capture position (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if ( safeReadPos < (DWORD)nextReadPos ) safeReadPos += dsBufferSize; // unwrap offset } } #ifdef GENERATE_DEBUG_LOG readTime = timeGetTime(); #endif if (statistics.readDeviceSafeLeadBytes < dsPointerDifference(currentReadPos,nextReadPos ,dsBufferSize)) { statistics.readDeviceSafeLeadBytes = dsPointerDifference(currentReadPos,nextReadPos ,dsBufferSize); } // Lock free space in the buffer result = dsBuffer->Lock (nextReadPos, buffer_bytes, &buffer1, &bufferSize1, &buffer2, &bufferSize2, 0); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to lock buffer during capture (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } if (duplexPrerollBytes <= 0) { // Copy our buffer into the DS buffer CopyMemory(buffer, buffer1, bufferSize1); if (buffer2 != NULL) CopyMemory(buffer+bufferSize1, buffer2, bufferSize2); } else { memset(buffer,0,bufferSize1); if (buffer2 != NULL) memset(buffer+bufferSize1,0,bufferSize2); duplexPrerollBytes -= bufferSize1 + bufferSize2; } // Update our buffer offset and unlock sound buffer nextReadPos = (nextReadPos + bufferSize1 + bufferSize2) % dsBufferSize; dsBuffer->Unlock (buffer1, bufferSize1, buffer2, bufferSize2); if ( FAILED(result) ) { sprintf(message_, "RtApiDs: Unable to unlock buffer during capture (%s): %s.", devices_[stream_.device[1]].name.c_str(), getErrorString(result)); error(RtError::DRIVER_ERROR); } handles[1].bufferPointer = nextReadPos; // No byte swapping necessary in DirectSound implementation. // If necessary, convert 8-bit data from unsigned to signed. if ( stream_.deviceFormat[1] == RTAUDIO_SINT8 ) for ( int j=0; jstopStream(); } // Definitions for utility functions and callbacks // specific to the DirectSound implementation. // chuck #if defined(__WINDOWS_PTHREAD__) extern "C" void * callbackHandler( void * ptr ) { CallbackInfo *info = (CallbackInfo *) ptr; RtApiDs *object = (RtApiDs *) info->object; bool *usingCallback = &info->usingCallback; while ( *usingCallback ) { pthread_testcancel(); try { object->tickStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiDs: callback thread error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_log( CK_LOG_INFO, "closing thread..." ); EM_poplog(); break; } } return 0; } #else extern "C" unsigned __stdcall callbackHandler(void *ptr) { CallbackInfo *info = (CallbackInfo *) ptr; RtApiDs *object = (RtApiDs *) info->object; bool *usingCallback = &info->usingCallback; while ( *usingCallback ) { try { object->tickStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiDs: callback thread error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); if( exception.getContinue() ) { EM_log( CK_LOG_INFO, "closing overridden - continuing..." ); EM_poplog(); usleep( 100000 ); } else { EM_log( CK_LOG_INFO, "closing thread..." ); EM_poplog(); break; } } } _endthreadex( 0 ); return 0; } #endif static bool CALLBACK deviceCountCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { int *pointer = ((int *) lpContext); (*pointer)++; return true; } static bool CALLBACK deviceInfoCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { enum_info *info = ((enum_info *) lpContext); while (strlen(info->name) > 0) info++; strncpy(info->name, lpcstrDescription, 64); info->id = lpguid; HRESULT hr; info->isValid = false; if (info->isInput == true) { DSCCAPS caps; LPDIRECTSOUNDCAPTURE object; hr = DirectSoundCaptureCreate( lpguid, &object, NULL ); if( hr != DS_OK ) return true; caps.dwSize = sizeof(caps); hr = object->GetCaps( &caps ); if( hr == DS_OK ) { if (caps.dwChannels > 0 && caps.dwFormats > 0) info->isValid = true; } object->Release(); } else { DSCAPS caps; LPDIRECTSOUND object; hr = DirectSoundCreate( lpguid, &object, NULL ); if( hr != DS_OK ) return true; caps.dwSize = sizeof(caps); hr = object->GetCaps( &caps ); if( hr == DS_OK ) { if ( caps.dwFlags & DSCAPS_PRIMARYMONO || caps.dwFlags & DSCAPS_PRIMARYSTEREO ) info->isValid = true; } object->Release(); } return true; } static bool CALLBACK defaultDeviceCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { enum_info *info = ((enum_info *) lpContext); if ( lpguid == NULL ) { strncpy(info->name, lpcstrDescription, 64); return false; } return true; } static bool CALLBACK deviceIdCallback(LPGUID lpguid, LPCSTR lpcstrDescription, LPCSTR lpcstrModule, LPVOID lpContext) { enum_info *info = ((enum_info *) lpContext); if ( strncmp( info->name, lpcstrDescription, 64 ) == 0 ) { info->id = lpguid; info->isValid = true; return false; } return true; } static char* getErrorString(int code) { switch (code) { case DSERR_ALLOCATED: return "Already allocated."; case DSERR_CONTROLUNAVAIL: return "Control unavailable."; case DSERR_INVALIDPARAM: return "Invalid parameter."; case DSERR_INVALIDCALL: return "Invalid call."; case DSERR_GENERIC: return "Generic error."; case DSERR_PRIOLEVELNEEDED: return "Priority level needed"; case DSERR_OUTOFMEMORY: return "Out of memory"; case DSERR_BADFORMAT: return "The sample rate or the channel format is not supported."; case DSERR_UNSUPPORTED: return "Not supported."; case DSERR_NODRIVER: return "No driver."; case DSERR_ALREADYINITIALIZED: return "Already initialized."; case DSERR_NOAGGREGATION: return "No aggregation."; case DSERR_BUFFERLOST: return "Buffer lost."; case DSERR_OTHERAPPHASPRIO: return "Another application already has priority."; case DSERR_UNINITIALIZED: return "Uninitialized."; default: return "DirectSound unknown error"; } } //******************** End of __WINDOWS_DS__ *********************// #endif #if defined(__IRIX_AL__) // SGI's AL API for IRIX #include #include #include extern "C" void *callbackHandler(void * ptr); RtApiAl :: RtApiAl() { this->initialize(); if (nDevices_ <= 0) { sprintf(message_, "RtApiAl: no Irix AL audio devices found!"); error(RtError::NO_DEVICES_FOUND); } } RtApiAl :: ~RtApiAl() { // The subclass destructor gets called before the base class // destructor, so close any existing streams before deallocating // apiDeviceId memory. if ( stream_.mode != UNINITIALIZED ) closeStream(); // Free our allocated apiDeviceId memory. long *id; for ( unsigned int i=0; iapiDeviceId; resource = id[0]; if (resource > 0) { // Probe output device parameters. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0); if (result < 0) { sprintf(message_, "RtApiAl: error getting device (%s) channels: %s.", info->name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); } else { info->maxOutputChannels = value.i; info->minOutputChannels = 1; } result = alGetParamInfo(resource, AL_RATE, &pinfo); if (result < 0) { sprintf(message_, "RtApiAl: error getting device (%s) rates: %s.", info->name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); } else { info->sampleRates.clear(); for (unsigned int k=0; k= pinfo.min.i && SAMPLE_RATES[k] <= pinfo.max.i ) info->sampleRates.push_back( SAMPLE_RATES[k] ); } } // The AL library supports all our formats, except 24-bit and 32-bit ints. info->nativeFormats = (RtAudioFormat) 51; } // Now get input resource ID if it exists. resource = id[1]; if (resource > 0) { // Probe input device parameters. result = alQueryValues(resource, AL_CHANNELS, &value, 1, 0, 0); if (result < 0) { sprintf(message_, "RtApiAl: error getting device (%s) channels: %s.", info->name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); } else { info->maxInputChannels = value.i; info->minInputChannels = 1; } result = alGetParamInfo(resource, AL_RATE, &pinfo); if (result < 0) { sprintf(message_, "RtApiAl: error getting device (%s) rates: %s.", info->name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); } else { // In the case of the default device, these values will // overwrite the rates determined for the output device. Since // the input device is most likely to be more limited than the // output device, this is ok. info->sampleRates.clear(); for (unsigned int k=0; k= pinfo.min.i && SAMPLE_RATES[k] <= pinfo.max.i ) info->sampleRates.push_back( SAMPLE_RATES[k] ); } } // The AL library supports all our formats, except 24-bit and 32-bit ints. info->nativeFormats = (RtAudioFormat) 51; } if ( info->maxInputChannels == 0 && info->maxOutputChannels == 0 ) return; if ( info->sampleRates.size() == 0 ) return; // Determine duplex status. if (info->maxInputChannels < info->maxOutputChannels) info->maxDuplexChannels = info->maxInputChannels; else info->maxDuplexChannels = info->maxOutputChannels; if (info->minInputChannels < info->minOutputChannels) info->minDuplexChannels = info->minInputChannels; else info->minDuplexChannels = info->minOutputChannels; if ( info->maxDuplexChannels > 0 ) info->hasDuplexSupport = true; else info->hasDuplexSupport = false; info->probed = true; return; } bool RtApiAl :: probeDeviceOpen(int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers) { int result, nBuffers; long resource; ALconfig al_config; ALport port; ALpv pvs[2]; long *id = (long *) devices_[device].apiDeviceId; // Get a new ALconfig structure. al_config = alNewConfig(); if ( !al_config ) { sprintf(message_,"RtApiAl: can't get AL config: %s.", alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the channels. result = alSetChannels(al_config, channels); if ( result < 0 ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: can't set %d channels in AL config: %s.", channels, alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Attempt to set the queue size. The al API doesn't provide a // means for querying the minimum/maximum buffer size of a device, // so if the specified size doesn't work, take whatever the // al_config structure returns. if ( numberOfBuffers < 1 ) nBuffers = 1; else nBuffers = numberOfBuffers; long buffer_size = *bufferSize * nBuffers; result = alSetQueueSize(al_config, buffer_size); // in sample frames if ( result < 0 ) { // Get the buffer size specified by the al_config and try that. buffer_size = alGetQueueSize(al_config); result = alSetQueueSize(al_config, buffer_size); if ( result < 0 ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: can't set buffer size (%ld) in AL config: %s.", buffer_size, alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } *bufferSize = buffer_size / nBuffers; } // Set the data format. stream_.userFormat = format; stream_.deviceFormat[mode] = format; if (format == RTAUDIO_SINT8) { result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP); result = alSetWidth(al_config, AL_SAMPLE_8); } else if (format == RTAUDIO_SINT16) { result = alSetSampFmt(al_config, AL_SAMPFMT_TWOSCOMP); result = alSetWidth(al_config, AL_SAMPLE_16); } else if (format == RTAUDIO_SINT24) { // Our 24-bit format assumes the upper 3 bytes of a 4 byte word. // The AL library uses the lower 3 bytes, so we'll need to do our // own conversion. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT); stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; } else if (format == RTAUDIO_SINT32) { // The AL library doesn't seem to support the 32-bit integer // format, so we'll need to do our own conversion. result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT); stream_.deviceFormat[mode] = RTAUDIO_FLOAT32; } else if (format == RTAUDIO_FLOAT32) result = alSetSampFmt(al_config, AL_SAMPFMT_FLOAT); else if (format == RTAUDIO_FLOAT64) result = alSetSampFmt(al_config, AL_SAMPFMT_DOUBLE); if ( result == -1 ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: error setting sample format in AL config: %s.", alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } if (mode == OUTPUT) { // Set our device. if (device == 0) resource = AL_DEFAULT_OUTPUT; else resource = id[0]; result = alSetDevice(al_config, resource); if ( result == -1 ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: error setting device (%s) in AL config: %s.", devices_[device].name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Open the port. port = alOpenPort("RtApiAl Output Port", "w", al_config); if( !port ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: error opening output port: %s.", alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the sample rate pvs[0].param = AL_MASTER_CLOCK; pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE; pvs[1].param = AL_RATE; pvs[1].value.ll = alDoubleToFixed((double)sampleRate); result = alSetParams(resource, pvs, 2); if ( result < 0 ) { alClosePort(port); alFreeConfig(al_config); sprintf(message_,"RtApiAl: error setting sample rate (%d) for device (%s): %s.", sampleRate, devices_[device].name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } } else { // mode == INPUT // Set our device. if (device == 0) resource = AL_DEFAULT_INPUT; else resource = id[1]; result = alSetDevice(al_config, resource); if ( result == -1 ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: error setting device (%s) in AL config: %s.", devices_[device].name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Open the port. port = alOpenPort("RtApiAl Input Port", "r", al_config); if( !port ) { alFreeConfig(al_config); sprintf(message_,"RtApiAl: error opening input port: %s.", alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } // Set the sample rate pvs[0].param = AL_MASTER_CLOCK; pvs[0].value.i = AL_CRYSTAL_MCLK_TYPE; pvs[1].param = AL_RATE; pvs[1].value.ll = alDoubleToFixed((double)sampleRate); result = alSetParams(resource, pvs, 2); if ( result < 0 ) { alClosePort(port); alFreeConfig(al_config); sprintf(message_,"RtApiAl: error setting sample rate (%d) for device (%s): %s.", sampleRate, devices_[device].name.c_str(), alGetErrorString(oserror())); error(RtError::DEBUG_WARNING); return FAILURE; } } alFreeConfig(al_config); stream_.nUserChannels[mode] = channels; stream_.nDeviceChannels[mode] = channels; // Save stream handle. ALport *handle = (ALport *) stream_.apiHandle; if ( handle == 0 ) { handle = (ALport *) calloc(2, sizeof(ALport)); if ( handle == NULL ) { sprintf(message_, "RtApiAl: Irix Al error allocating handle memory (%s).", devices_[device].name.c_str()); goto error; } stream_.apiHandle = (void *) handle; handle[0] = 0; handle[1] = 0; } handle[mode] = port; // Set flags for buffer conversion stream_.doConvertBuffer[mode] = false; if (stream_.userFormat != stream_.deviceFormat[mode]) stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers if ( stream_.nUserChannels[0] != stream_.nUserChannels[1] ) { long buffer_bytes; if (stream_.nUserChannels[0] >= stream_.nUserChannels[1]) buffer_bytes = stream_.nUserChannels[0]; else buffer_bytes = stream_.nUserChannels[1]; buffer_bytes *= *bufferSize * formatBytes(stream_.userFormat); if (stream_.userBuffer) free(stream_.userBuffer); stream_.userBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.userBuffer == NULL) { sprintf(message_, "RtApiAl: error allocating user buffer memory (%s).", devices_[device].name.c_str()); goto error; } } if ( stream_.doConvertBuffer[mode] ) { long buffer_bytes; bool makeBuffer = true; if ( mode == OUTPUT ) buffer_bytes = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); else { // mode == INPUT buffer_bytes = stream_.nDeviceChannels[1] * formatBytes(stream_.deviceFormat[1]); if ( stream_.mode == OUTPUT && stream_.deviceBuffer ) { long bytes_out = stream_.nDeviceChannels[0] * formatBytes(stream_.deviceFormat[0]); if ( buffer_bytes < bytes_out ) makeBuffer = false; } } if ( makeBuffer ) { buffer_bytes *= *bufferSize; if (stream_.deviceBuffer) free(stream_.deviceBuffer); stream_.deviceBuffer = (char *) calloc(buffer_bytes, 1); if (stream_.deviceBuffer == NULL) { sprintf(message_, "RtApiAl: error allocating device buffer memory (%s).", devices_[device].name.c_str()); goto error; } } } stream_.device[mode] = device; stream_.state = STREAM_STOPPED; if ( stream_.mode == OUTPUT && mode == INPUT ) // We had already set up an output stream. stream_.mode = DUPLEX; else stream_.mode = mode; stream_.nBuffers = nBuffers; stream_.bufferSize = *bufferSize; stream_.sampleRate = sampleRate; // Setup the buffer conversion information structure. if ( stream_.doConvertBuffer[mode] ) { if (mode == INPUT) { // convert device to user buffer stream_.convertInfo[mode].inJump = stream_.nDeviceChannels[1]; stream_.convertInfo[mode].outJump = stream_.nUserChannels[1]; stream_.convertInfo[mode].inFormat = stream_.deviceFormat[1]; stream_.convertInfo[mode].outFormat = stream_.userFormat; } else { // convert user to device buffer stream_.convertInfo[mode].inJump = stream_.nUserChannels[0]; stream_.convertInfo[mode].outJump = stream_.nDeviceChannels[0]; stream_.convertInfo[mode].inFormat = stream_.userFormat; stream_.convertInfo[mode].outFormat = stream_.deviceFormat[0]; } if ( stream_.convertInfo[mode].inJump < stream_.convertInfo[mode].outJump ) stream_.convertInfo[mode].channels = stream_.convertInfo[mode].inJump; else stream_.convertInfo[mode].channels = stream_.convertInfo[mode].outJump; // Set up the interleave/deinterleave offsets. if ( mode == INPUT && stream_.deInterleave[1] ) { for (int k=0; k err) frames = err; } frames = stream_.bufferSize - frames; if (frames < 0) frames = 0; MUTEX_UNLOCK(&stream_.mutex); return frames; } void RtApiAl :: tickStream() { verifyStream(); int stopStream = 0; if (stream_.state == STREAM_STOPPED) { if (stream_.callbackInfo.usingCallback) usleep(50000); // sleep 50 milliseconds return; } else if (stream_.callbackInfo.usingCallback) { RtAudioCallback callback = (RtAudioCallback) stream_.callbackInfo.callback; stopStream = callback(stream_.userBuffer, stream_.bufferSize, stream_.callbackInfo.userData); } MUTEX_LOCK(&stream_.mutex); // The state might change while waiting on a mutex. if (stream_.state == STREAM_STOPPED) goto unlock; char *buffer; int channels; RtAudioFormat format; ALport *handle = (ALport *) stream_.apiHandle; if (stream_.mode == OUTPUT || stream_.mode == DUPLEX) { // Setup parameters and do buffer conversion if necessary. if (stream_.doConvertBuffer[0]) { buffer = stream_.deviceBuffer; convertBuffer( buffer, stream_.userBuffer, stream_.convertInfo[0] ); channels = stream_.nDeviceChannels[0]; format = stream_.deviceFormat[0]; } else { buffer = stream_.userBuffer; channels = stream_.nUserChannels[0]; format = stream_.userFormat; } // Do byte swapping if necessary. if (stream_.doByteSwap[0]) byteSwapBuffer(buffer, stream_.bufferSize * channels, format); // Write interleaved samples to device. alWriteFrames(handle[0], buffer, stream_.bufferSize); } if (stream_.mode == INPUT || stream_.mode == DUPLEX) { // Setup parameters. if (stream_.doConvertBuffer[1]) { buffer = stream_.deviceBuffer; channels = stream_.nDeviceChannels[1]; format = stream_.deviceFormat[1]; } else { buffer = stream_.userBuffer; channels = stream_.nUserChannels[1]; format = stream_.userFormat; } // Read interleaved samples from device. alReadFrames(handle[1], buffer, stream_.bufferSize); // Do byte swapping if necessary. if (stream_.doByteSwap[1]) byteSwapBuffer(buffer, stream_.bufferSize * channels, format); // Do buffer conversion if necessary. if (stream_.doConvertBuffer[1]) convertBuffer( stream_.userBuffer, stream_.deviceBuffer, stream_.convertInfo[1] ); } unlock: MUTEX_UNLOCK(&stream_.mutex); if (stream_.callbackInfo.usingCallback && stopStream) this->stopStream(); } void RtApiAl :: setStreamCallback(RtAudioCallback callback, void *userData) { verifyStream(); CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo; if ( info->usingCallback ) { sprintf(message_, "RtApiAl: A callback is already set for this stream!"); error(RtError::WARNING); return; } info->callback = (void *) callback; info->userData = userData; info->usingCallback = true; info->object = (void *) this; // Set the thread attributes for joinable and realtime scheduling // priority. The higher priority will only take affect if the // program is run as root or suid. pthread_attr_t attr; pthread_attr_init(&attr); // chuck (commented out) // pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); // pthread_attr_setschedpolicy(&attr, SCHED_RR); int err = pthread_create(&info->thread, &attr, callbackHandler, &stream_.callbackInfo); pthread_attr_destroy(&attr); if (err) { info->usingCallback = false; sprintf(message_, "RtApiAl: error starting callback thread!"); error(RtError::THREAD_ERROR); } } void RtApiAl :: cancelStreamCallback() { verifyStream(); if (stream_.callbackInfo.usingCallback) { if (stream_.state == STREAM_RUNNING) stopStream(); MUTEX_LOCK(&stream_.mutex); stream_.callbackInfo.usingCallback = false; pthread_join(stream_.callbackInfo.thread, NULL); stream_.callbackInfo.thread = 0; stream_.callbackInfo.callback = NULL; stream_.callbackInfo.userData = NULL; MUTEX_UNLOCK(&stream_.mutex); } } extern "C" void *callbackHandler(void *ptr) { CallbackInfo *info = (CallbackInfo *) ptr; RtApiAl *object = (RtApiAl *) info->object; bool *usingCallback = &info->usingCallback; while ( *usingCallback ) { try { object->tickStream(); } catch (RtError &exception) { EM_log( CK_LOG_SYSTEM, "RtApiAl: callback thread error..." ); EM_pushlog(); EM_log( CK_LOG_INFO, "(%s)", exception.getMessageString() ); EM_log( CK_LOG_INFO, "closing thread..." ); EM_poplog(); break; } } return 0; } //******************** End of __IRIX_AL__ *********************// #endif // *************************************************** // // // Protected common (OS-independent) RtAudio methods. // // *************************************************** // // This method can be modified to control the behavior of error // message reporting and throwing. void RtApi :: error(RtError::Type type, long cont) { if (type == RtError::WARNING) { #if defined(__CHUCK_DEBUG__) fprintf(stderr, "[chuck](via rtaudio): %s\n", message_); #endif } else if (type == RtError::DEBUG_WARNING) { #if defined(__CHUCK_DEBUG__) #if defined(__RTAUDIO_DEBUG__) fprintf(stderr, "[chuck](via rtaudio): %s\n", message_); #endif #endif } else { #if defined(__RTAUDIO_DEBUG__) fprintf(stderr, "[chuck](via rtaudio): %s\n", message_); #endif throw RtError(std::string(message_), type, cont); } } void RtApi :: verifyStream() { if ( stream_.mode == UNINITIALIZED ) { sprintf(message_, "RtAudio: stream is not open!"); error(RtError::INVALID_STREAM); } } void RtApi :: clearDeviceInfo(RtApiDevice *info) { // Don't clear the name or DEVICE_ID fields here ... they are // typically set prior to a call of this function. info->probed = false; info->maxOutputChannels = 0; info->maxInputChannels = 0; info->maxDuplexChannels = 0; info->minOutputChannels = 0; info->minInputChannels = 0; info->minDuplexChannels = 0; info->hasDuplexSupport = false; info->sampleRates.clear(); info->nativeFormats = 0; } void RtApi :: clearStreamInfo() { stream_.mode = UNINITIALIZED; stream_.state = STREAM_STOPPED; stream_.sampleRate = 0; stream_.bufferSize = 0; stream_.nBuffers = 0; stream_.userFormat = 0; for ( int i=0; i<2; i++ ) { stream_.device[i] = 0; stream_.doConvertBuffer[i] = false; stream_.deInterleave[i] = false; stream_.doByteSwap[i] = false; stream_.nUserChannels[i] = 0; stream_.nDeviceChannels[i] = 0; stream_.deviceFormat[i] = 0; } } int RtApi :: formatBytes(RtAudioFormat format) { if (format == RTAUDIO_SINT16) return 2; else if (format == RTAUDIO_SINT24 || format == RTAUDIO_SINT32 || format == RTAUDIO_FLOAT32) return 4; else if (format == RTAUDIO_FLOAT64) return 8; else if (format == RTAUDIO_SINT8) return 1; sprintf(message_,"(via rtaudio): undefined format in formatBytes()."); error(RtError::WARNING); return 0; } void RtApi :: convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ) { // This function does format conversion, input/output channel compensation, and // data interleaving/deinterleaving. 24-bit integers are assumed to occupy // the upper three bytes of a 32-bit integer. // Clear our device buffer when in/out duplex device channels are different if ( outBuffer == stream_.deviceBuffer && stream_.mode == DUPLEX && stream_.nDeviceChannels[0] != stream_.nDeviceChannels[1] ) memset( outBuffer, 0, stream_.bufferSize * info.outJump * formatBytes( info.outFormat ) ); int j; if (info.outFormat == RTAUDIO_FLOAT64) { Float64 scale; Float64 *out = (Float64 *)outBuffer; if (info.inFormat == RTAUDIO_SINT8) { signed char *in = (signed char *)inBuffer; scale = 1.0 / 128.0; for (int i=0; i> 16) & 0x0000ffff); } in += info.inJump; out += info.outJump; } } else if (info.inFormat == RTAUDIO_SINT32) { Int32 *in = (Int32 *)inBuffer; for (int i=0; i> 16) & 0x0000ffff); } in += info.inJump; out += info.outJump; } } else if (info.inFormat == RTAUDIO_FLOAT32) { Float32 *in = (Float32 *)inBuffer; for (int i=0; i> 8) & 0x00ff); } in += info.inJump; out += info.outJump; } } else if (info.inFormat == RTAUDIO_SINT24) { Int32 *in = (Int32 *)inBuffer; for (int i=0; i> 24) & 0x000000ff); } in += info.inJump; out += info.outJump; } } else if (info.inFormat == RTAUDIO_SINT32) { Int32 *in = (Int32 *)inBuffer; for (int i=0; i> 24) & 0x000000ff); } in += info.inJump; out += info.outJump; } } else if (info.inFormat == RTAUDIO_FLOAT32) { Float32 *in = (Float32 *)inBuffer; for (int i=0; i #include // Operating system dependent thread functionality. #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) #include #if defined(__WINDOWS_PTHREAD__) #include typedef pthread_t ThreadHandle; typedef pthread_mutex_t StreamMutex; #else #include typedef unsigned long ThreadHandle; typedef CRITICAL_SECTION StreamMutex; #endif #else // Various unix flavors with pthread support. #include typedef pthread_t ThreadHandle; typedef pthread_mutex_t StreamMutex; #endif // This global structure type is used to pass callback information // between the private RtAudio stream structure and global callback // handling functions. struct CallbackInfo { void *object; // Used as a "this" pointer. ThreadHandle thread; bool usingCallback; void *callback; void *userData; void *apiInfo; // void pointer for API specific callback information // Default constructor. CallbackInfo() :object(0), usingCallback(false), callback(0), userData(0), apiInfo(0) {} }; // Support for signed integers and floats. Audio data fed to/from // the tickStream() routine is assumed to ALWAYS be in host // byte order. The internal routines will automatically take care of // any necessary byte-swapping between the host format and the // soundcard. Thus, endian-ness is not a concern in the following // format definitions. typedef unsigned long RtAudioFormat; static const RtAudioFormat RTAUDIO_SINT8 = 0x1; /*!< 8-bit signed integer. */ static const RtAudioFormat RTAUDIO_SINT16 = 0x2; /*!< 16-bit signed integer. */ static const RtAudioFormat RTAUDIO_SINT24 = 0x4; /*!< Upper 3 bytes of 32-bit signed integer. */ static const RtAudioFormat RTAUDIO_SINT32 = 0x8; /*!< 32-bit signed integer. */ static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; /*!< Normalized between plus/minus 1.0. */ static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; /*!< Normalized between plus/minus 1.0. */ typedef int (*RtAudioCallback)(char *buffer, int bufferSize, void *userData); //! The public device information structure for returning queried values. struct RtAudioDeviceInfo { std::string name; /*!< Character string device identifier. */ bool probed; /*!< true if the device capabilities were successfully probed. */ int outputChannels; /*!< Maximum output channels supported by device. */ int inputChannels; /*!< Maximum input channels supported by device. */ int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ bool isDefault; /*!< true if this is the default output or input device. */ std::vector sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ // Default constructor. RtAudioDeviceInfo() :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), isDefault(false), nativeFormats(0) {} }; // **************************************************************** // // // RtApi class declaration. // // Note that RtApi is an abstract base class and cannot be // explicitly instantiated. The class RtAudio will create an // instance of an RtApi subclass (RtApiOss, RtApiAlsa, // RtApiJack, RtApiCore, RtApiAl, RtApiDs, or RtApiAsio). // // **************************************************************** // class RtApi { public: enum StreamState { STREAM_STOPPED, STREAM_RUNNING }; RtApi(); virtual ~RtApi(); void openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers ); void openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers ); virtual void setStreamCallback( RtAudioCallback callback, void *userData ) = 0; virtual void cancelStreamCallback() = 0; int getDeviceCount(void); RtAudioDeviceInfo getDeviceInfo( int device ); char * const getStreamBuffer(); RtApi::StreamState getStreamState() const; virtual void tickStream() = 0; virtual void closeStream(); virtual void startStream() = 0; virtual void stopStream() = 0; virtual void abortStream() = 0; protected: static const unsigned int MAX_SAMPLE_RATES; static const unsigned int SAMPLE_RATES[]; enum { FAILURE, SUCCESS }; enum StreamMode { OUTPUT, INPUT, DUPLEX, UNINITIALIZED = -75 }; // A protected structure used for buffer conversion. struct ConvertInfo { int channels; int inJump, outJump; RtAudioFormat inFormat, outFormat; std::vector inOffset; std::vector outOffset; }; // A protected structure for audio streams. struct RtApiStream { int device[2]; // Playback and record, respectively. void *apiHandle; // void pointer for API specific stream handle information StreamMode mode; // OUTPUT, INPUT, or DUPLEX. StreamState state; // STOPPED or RUNNING char *userBuffer; char *deviceBuffer; bool doConvertBuffer[2]; // Playback and record, respectively. bool deInterleave[2]; // Playback and record, respectively. bool doByteSwap[2]; // Playback and record, respectively. int sampleRate; int bufferSize; int nBuffers; int nUserChannels[2]; // Playback and record, respectively. int nDeviceChannels[2]; // Playback and record channels, respectively. RtAudioFormat userFormat; RtAudioFormat deviceFormat[2]; // Playback and record, respectively. StreamMutex mutex; CallbackInfo callbackInfo; ConvertInfo convertInfo[2]; RtApiStream() :apiHandle(0), mode((enum RtApi::StreamMode)-75), userBuffer(0), deviceBuffer(0) {} }; // A protected device structure for audio devices. struct RtApiDevice { std::string name; /*!< Character string device identifier. */ bool probed; /*!< true if the device capabilities were successfully probed. */ void *apiDeviceId; // void pointer for API specific device information int maxOutputChannels; /*!< Maximum output channels supported by device. */ int maxInputChannels; /*!< Maximum input channels supported by device. */ int maxDuplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ int minOutputChannels; /*!< Minimum output channels supported by device. */ int minInputChannels; /*!< Minimum input channels supported by device. */ int minDuplexChannels; /*!< Minimum simultaneous input/output channels supported by device. */ bool hasDuplexSupport; /*!< true if device supports duplex mode. */ bool isDefault; /*!< true if this is the default output or input device. */ std::vector sampleRates; /*!< Supported sample rates. */ RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ // Default constructor. RtApiDevice() :probed(false), apiDeviceId(0), maxOutputChannels(0), maxInputChannels(0), maxDuplexChannels(0), minOutputChannels(0), minInputChannels(0), minDuplexChannels(0), isDefault(false), nativeFormats(0) {} }; typedef signed short Int16; typedef signed int Int32; typedef float Float32; typedef double Float64; char message_[1024]; int nDevices_; std::vector devices_; RtApiStream stream_; /*! Protected, api-specific method to count and identify the system audio devices. This function MUST be implemented by all subclasses. */ virtual void initialize(void) = 0; /*! Protected, api-specific method which attempts to fill an RtAudioDevice structure for a given device. This function MUST be implemented by all subclasses. If an error is encountered during the probe, a "warning" message is reported and the value of "probed" remains false (no exception is thrown). A successful probe is indicated by probed = true. */ virtual void probeDeviceInfo( RtApiDevice *info ); /*! Protected, api-specific method which attempts to open a device with the given parameters. This function MUST be implemented by all subclasses. If an error is encountered during the probe, a "warning" message is reported and FAILURE is returned (no exception is thrown). A successful probe is indicated by a return value of SUCCESS. */ virtual bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); /*! Protected method which returns the index in the devices array to the default input device. */ virtual int getDefaultInputDevice(void); /*! Protected method which returns the index in the devices array to the default output device. */ virtual int getDefaultOutputDevice(void); //! Protected common method to clear an RtApiDevice structure. void clearDeviceInfo( RtApiDevice *info ); //! Protected common method to clear an RtApiStream structure. void clearStreamInfo(); //! Protected common error method to allow global control over error handling. void error( RtError::Type type, long cont = 0 ); /*! Protected common method used to check whether a stream is open. If not, an "invalid identifier" exception is thrown. */ void verifyStream(); /*! Protected method used to perform format, channel number, and/or interleaving conversions between the user and device buffers. */ void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); //! Protected common method used to perform byte-swapping on buffers. void byteSwapBuffer( char *buffer, int samples, RtAudioFormat format ); //! Protected common method which returns the number of bytes for a given format. int formatBytes( RtAudioFormat format ); }; // **************************************************************** // // // RtAudio class declaration. // // RtAudio is a "controller" used to select an available audio i/o // interface. It presents a common API for the user to call but all // functionality is implemented by the class RtAudioApi and its // subclasses. RtAudio creates an instance of an RtAudioApi subclass // based on the user's API choice. If no choice is made, RtAudio // attempts to make a "logical" API selection. // // **************************************************************** // class RtAudio { public: //! Audio API specifier arguments. enum RtAudioApi { UNSPECIFIED, /*!< Search for a working compiled API. */ LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ LINUX_OSS, /*!< The Linux Open Sound System API. */ LINUX_JACK, /*!< The Linux Jack Low-Latency Audio Server API. */ MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ IRIX_AL, /*!< The Irix Audio Library API. */ WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ WINDOWS_DS /*!< The Microsoft Direct Sound API. */ }; //! The default class constructor. /*! Probes the system to make sure at least one audio input/output device is available and determines the api-specific identifier for each device found. An RtError error can be thrown if no devices are found or if a memory allocation error occurs. If no API argument is specified and multiple API support has been compiled, the default order of use is JACK, ALSA, OSS (Linux systems) and ASIO, DS (Windows systems). */ RtAudio( RtAudioApi api=UNSPECIFIED ); //! A constructor which can be used to open a stream during instantiation. /*! The specified output and/or input device identifiers correspond to those enumerated via the getDeviceInfo() method. If device = 0, the default or first available devices meeting the given parameters is selected. If an output or input channel value is zero, the corresponding device value is ignored. When a stream is successfully opened, its identifier is returned via the "streamId" pointer. An RtError can be thrown if no devices are found for the given parameters, if a memory allocation error occurs, or if a driver error occurs. \sa openStream() */ RtAudio( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers, RtAudioApi api=UNSPECIFIED ); //! An overloaded constructor which opens a stream and also returns \c numberOfBuffers parameter via pointer argument. /*! See the previous constructor call for details. This overloaded version differs only in that it takes a pointer argument for the \c numberOfBuffers parameter and returns the value used by the audio device (which may be different from that requested). Note that the \c numberofBuffers parameter is not used with the Linux Jack, Macintosh CoreAudio, and Windows ASIO APIs. */ RtAudio( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers, RtAudioApi api=UNSPECIFIED ); //! The destructor. /*! Stops and closes an open stream and devices and deallocates buffer and structure memory. */ ~RtAudio(); //! A public method for opening a stream with the specified parameters. /*! An RtError is thrown if a stream cannot be opened. \param outputDevice: If equal to 0, the default or first device found meeting the given parameters is opened. Otherwise, the device number should correspond to one of those enumerated via the getDeviceInfo() method. \param outputChannels: The desired number of output channels. If equal to zero, the outputDevice identifier is ignored. \param inputDevice: If equal to 0, the default or first device found meeting the given parameters is opened. Otherwise, the device number should correspond to one of those enumerated via the getDeviceInfo() method. \param inputChannels: The desired number of input channels. If equal to zero, the inputDevice identifier is ignored. \param format: An RtAudioFormat specifying the desired sample data format. \param sampleRate: The desired sample rate (sample frames per second). \param *bufferSize: A pointer value indicating the desired internal buffer size in sample frames. The actual value used by the device is returned via the same pointer. A value of zero can be specified, in which case the lowest allowable value is determined. \param numberOfBuffers: A value which can be used to help control device latency. More buffers typically result in more robust performance, though at a cost of greater latency. A value of zero can be specified, in which case the lowest allowable value is used. */ void openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int numberOfBuffers ); //! A public method for opening a stream and also returning \c numberOfBuffers parameter via pointer argument. /*! See the previous function call for details. This overloaded version differs only in that it takes a pointer argument for the \c numberOfBuffers parameter and returns the value used by the audio device (which may be different from that requested). Note that the \c numberofBuffers parameter is not used with the Linux Jack, Macintosh CoreAudio, and Windows ASIO APIs. */ void openStream( int outputDevice, int outputChannels, int inputDevice, int inputChannels, RtAudioFormat format, int sampleRate, int *bufferSize, int *numberOfBuffers ); //! A public method which sets a user-defined callback function for a given stream. /*! This method assigns a callback function to a previously opened stream for non-blocking stream functionality. A separate process is initiated, though the user function is called only when the stream is "running" (between calls to the startStream() and stopStream() methods, respectively). The callback process remains active for the duration of the stream and is automatically shutdown when the stream is closed (via the closeStream() method or by object destruction). The callback process can also be shutdown and the user function de-referenced through an explicit call to the cancelStreamCallback() method. Note that the stream can use only blocking or callback functionality at a particular time, though it is possible to alternate modes on the same stream through the use of the setStreamCallback() and cancelStreamCallback() methods (the blocking tickStream() method can be used before a callback is set and/or after a callback is cancelled). An RtError will be thrown if called when no stream is open or a thread errors occurs. */ void setStreamCallback(RtAudioCallback callback, void *userData) { rtapi_->setStreamCallback( callback, userData ); }; //! A public method which cancels a callback process and function for the stream. /*! This method shuts down a callback process and de-references the user function for the stream. Callback functionality can subsequently be restarted on the stream via the setStreamCallback() method. An RtError will be thrown if called when no stream is open. */ void cancelStreamCallback() { rtapi_->cancelStreamCallback(); }; //! A public method which returns the number of audio devices found. int getDeviceCount(void) { return rtapi_->getDeviceCount(); }; //! Return an RtAudioDeviceInfo structure for a specified device number. /*! Any device integer between 1 and getDeviceCount() is valid. If a device is busy or otherwise unavailable, the structure member "probed" will have a value of "false" and all other members are undefined. If the specified device is the current default input or output device, the "isDefault" member will have a value of "true". An RtError will be thrown for an invalid device argument. */ RtAudioDeviceInfo getDeviceInfo(int device) { return rtapi_->getDeviceInfo( device ); }; //! A public method which returns a pointer to the buffer for an open stream. /*! The user should fill and/or read the buffer data in interleaved format and then call the tickStream() method. An RtError will be thrown if called when no stream is open. */ char * const getStreamBuffer() { return rtapi_->getStreamBuffer(); }; //! Public method used to trigger processing of input/output data for a stream. /*! This method blocks until all buffer data is read/written. An RtError will be thrown if a driver error occurs or if called when no stream is open. */ void tickStream() { rtapi_->tickStream(); }; //! Public method which closes a stream and frees any associated buffers. /*! If a stream is not open, this method issues a warning and returns (an RtError is not thrown). */ void closeStream() { rtapi_->closeStream(); }; //! Public method which starts a stream. /*! An RtError will be thrown if a driver error occurs or if called when no stream is open. */ void startStream() { rtapi_->startStream(); }; //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in. /*! An RtError will be thrown if a driver error occurs or if called when no stream is open. */ void stopStream() { rtapi_->stopStream(); }; //! Stop a stream, discarding any samples remaining in the input/output queue. /*! An RtError will be thrown if a driver error occurs or if called when no stream is open. */ void abortStream() { rtapi_->abortStream(); }; protected: void initialize( RtAudioApi api ); RtApi *rtapi_; }; // RtApi Subclass prototypes. #if defined(__LINUX_ALSA__) class RtApiAlsa: public RtApi { public: RtApiAlsa(); ~RtApiAlsa(); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); int streamWillBlock(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); }; #endif #if defined(__LINUX_JACK__) class RtApiJack: public RtApi { public: RtApiJack(); ~RtApiJack(); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! void callbackEvent( unsigned long nframes ); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); }; #endif #if defined(__LINUX_OSS__) class RtApiOss: public RtApi { public: RtApiOss(); ~RtApiOss(); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); int streamWillBlock(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); }; #endif #if defined(__MACOSX_CORE__) #include class RtApiCore: public RtApi { public: RtApiCore(); ~RtApiCore(); int getDefaultOutputDevice(void); int getDefaultInputDevice(void); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! void callbackEvent( AudioDeviceID deviceId, void *inData, void *outData ); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); }; #endif #if defined(__WINDOWS_DS__) class RtApiDs: public RtApi { public: RtApiDs(); ~RtApiDs(); int getDefaultOutputDevice(void); int getDefaultInputDevice(void); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); int streamWillBlock(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); public: // \brief Internal structure that provide debug information on the state of a running DSound device. struct RtDsStatistics { // \brief Sample Rate. long sampleRate; // \brief The size of one sample * number of channels on the input device. int inputFrameSize; // \brief The size of one sample * number of channels on the output device. int outputFrameSize; /* \brief The number of times the read pointer had to be adjusted to avoid reading from an unsafe buffer position. * * This field is only used when running in DUPLEX mode. INPUT mode devices just wait until the data is * available. */ int numberOfReadOverruns; // \brief The number of times the write pointer had to be adjusted to avoid writing in an unsafe buffer position. int numberOfWriteUnderruns; // \brief Number of bytes by attribute to buffer configuration by which writing must lead the current write pointer. int writeDeviceBufferLeadBytes; // \brief Number of bytes by attributable to the device driver by which writing must lead the current write pointer on this output device. unsigned long writeDeviceSafeLeadBytes; // \brief Number of bytes by which reading must trail the current read pointer on this input device. unsigned long readDeviceSafeLeadBytes; /* \brief Estimated latency in seconds. * * For INPUT mode devices, based the latency of the device's safe read pointer, plus one buffer's * worth of additional latency. * * For OUTPUT mode devices, the latency of the device's safe write pointer, plus N buffers of * additional buffer latency. * * For DUPLEX devices, the sum of latencies for both input and output devices. DUPLEX devices * also back off the read pointers an additional amount in order to maintain synchronization * between out-of-phase read and write pointers. This time is also included. * * Note that most software packages report latency between the safe write pointer * and the software lead pointer, excluding the hardware device's safe write pointer * latency. Figures of 1 or 2ms of latency on Windows audio devices are invariably of this type. * The reality is that hardware devices often have latencies of 30ms or more (often much * higher for duplex operation). */ double latency; }; // \brief Report on the current state of a running DSound device. static RtDsStatistics getDsStatistics(); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); bool coInitialized; bool buffersRolling; long duplexPrerollBytes; static RtDsStatistics statistics; }; #endif #if defined(__WINDOWS_ASIO__) class RtApiAsio: public RtApi { public: RtApiAsio(); ~RtApiAsio(); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! void callbackEvent( long bufferIndex ); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); bool coInitialized; }; #endif #if defined(__IRIX_AL__) class RtApiAl: public RtApi { public: RtApiAl(); ~RtApiAl(); int getDefaultOutputDevice(void); int getDefaultInputDevice(void); void tickStream(); void closeStream(); void startStream(); void stopStream(); void abortStream(); int streamWillBlock(); void setStreamCallback( RtAudioCallback callback, void *userData ); void cancelStreamCallback(); private: void initialize(void); void probeDeviceInfo( RtApiDevice *info ); bool probeDeviceOpen( int device, StreamMode mode, int channels, int sampleRate, RtAudioFormat format, int *bufferSize, int numberOfBuffers ); }; #endif // Define the following flag to have extra information spewed to stderr. //#define __RTAUDIO_DEBUG__ #endif chuck-1.2.0.8.dfsg/src/rterror.h0000644000175000017500000000415210600421721014777 0ustar piempiem/************************************************************************/ /*! \class RtError \brief Exception handling class for RtAudio & RtMidi. The RtError class is quite simple but it does allow errors to be "caught" by RtError::Type. See the RtAudio and RtMidi documentation to know which methods can throw an RtError. */ /************************************************************************/ #ifndef RTERROR_H #define RTERROR_H #include #include class RtError { public: //! Defined RtError types. enum Type { WARNING, /*!< A non-critical error. */ DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ UNSPECIFIED, /*!< The default, unspecified error type. */ NO_DEVICES_FOUND, /*!< No devices found on system. */ INVALID_DEVICE, /*!< An invalid device ID was specified. */ INVALID_STREAM, /*!< An invalid stream ID was specified. */ MEMORY_ERROR, /*!< An error occured during memory allocation. */ INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ DRIVER_ERROR, /*!< A system driver error occured. */ SYSTEM_ERROR, /*!< A system error occured. */ THREAD_ERROR /*!< A thread error occured. */ }; protected: std::string message_; Type type_; public: long continue_; //! The constructor. RtError(const std::string& message, Type type = RtError::UNSPECIFIED, long c = 0 ) : message_(message), type_(type), continue_(c) {} //! The destructor. virtual ~RtError(void) {}; //! Prints thrown error message to stderr. virtual void printMessage(void) { fprintf( stderr, "\n%s\n\n", message_.c_str() ); } //! Returns the thrown error message type. virtual const Type& getType(void) { return type_; } //! Returns the thrown error message string. virtual const std::string& getMessage(void) { return message_; } //! Returns the thrown error message as a C string. virtual const char *getMessageString(void) { return message_.c_str(); } // don't stop virtual const long getContinue() { return continue_; } }; #endif chuck-1.2.0.8.dfsg/src/rtmidi.cpp0000644000175000017500000021705510600421721015133 0ustar piempiem/**********************************************************************/ /*! \class RtMidi \brief An abstract base class for realtime MIDI input/output. This class implements some common functionality for the realtime MIDI input/output subclasses RtMidiIn and RtMidiOut. RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes Copyright (c) 2003-2005 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ // RtMidi: Version 1.0.4, 14 October 2005 // chuck #include "rtmidi.h" #include #include //*********************************************************************// // Common RtMidi Definitions //*********************************************************************// RtMidi :: RtMidi() : apiData_( 0 ), connected_( false ) { } // chuck void RtMidi :: error( RtError::Type type ) { if (type == RtError::WARNING) { std::cerr << "[chuck](via RtMidi): " << errorString_ << "\n"; } else if (type == RtError::DEBUG_WARNING) { #if defined(__RTMIDI_DEBUG__) std::cerr << "[chuck](via RtMidi): " << errorString_ << "\n"; #endif } else { // std::cerr << "[chuck](via RtMidi): " << errorString_ << "\n"; throw RtError( errorString_, type ); } } //*********************************************************************// // Common RtMidiIn Definitions //*********************************************************************// RtMidiIn :: RtMidiIn() : RtMidi() { this->initialize(); } void RtMidiIn :: setCallback( RtMidiCallback callback, void *userData ) { if ( inputData_.usingCallback ) { errorString_ = "RtMidiIn::setCallback: callback function is already set!"; error( RtError::WARNING ); return; } if ( !callback ) { errorString_ = "RtMidiIn::setCallback: callback function value is invalid!"; error( RtError::WARNING ); return; } inputData_.userCallback = (void *) callback; inputData_.userData = userData; inputData_.usingCallback = true; } void RtMidiIn :: cancelCallback() { if ( !inputData_.usingCallback ) { errorString_ = "RtMidiIn::cancelCallback: no callback function was set!"; error( RtError::WARNING ); return; } inputData_.userCallback = 0; inputData_.userData = 0; inputData_.usingCallback = false; } void RtMidiIn :: setQueueSizeLimit( unsigned int queueSize ) { inputData_.queueLimit = queueSize; } void RtMidiIn :: ignoreTypes( bool midiSysex, bool midiTime, bool midiSense ) { inputData_.ignoreFlags = 0; if ( midiSysex ) inputData_.ignoreFlags = 0x01; if ( midiTime ) inputData_.ignoreFlags |= 0x02; if ( midiSense ) inputData_.ignoreFlags |= 0x04; } double RtMidiIn :: getMessage( std::vector *message ) { message->clear(); if ( inputData_.usingCallback ) { errorString_ = "RtMidiIn::getNextMessage: user callback is currently set for this port."; error( RtError::WARNING ); return 0.0; } if ( inputData_.queue.size() == 0 ) return 0.0; // Copy queued message to the vector pointer argument and then "pop" it. std::vector *bytes = &(inputData_.queue.front().bytes); message->assign( bytes->begin(), bytes->end() ); double deltaTime = inputData_.queue.front().timeStamp; inputData_.queue.pop(); return deltaTime; } //*********************************************************************// // Common RtMidiOut Definitions //*********************************************************************// RtMidiOut :: RtMidiOut() : RtMidi() { this->initialize(); } //*********************************************************************// // API: Macintosh OS-X //*********************************************************************// // API information found at: // - http://developer. apple .com/audio/pdf/coreaudio.pdf #if defined(__MACOSX_CORE__) // The CoreMIDI API is based on the use of a callback function for // MIDI input. We convert the system specific time stamps to delta // time values. // OS-X CoreMIDI header files. #include #include // CoreMIDI naming helper function prototypes static void readable_name(MIDIEndpointRef end, char *buffer, int bufsize); static int get_device_name(SInt32 uniqueid, char*buffer, int bufsize); // A structure to hold variables related to the CoreMIDI API // implementation. struct CoreMidiData { MIDIClientRef client; MIDIPortRef port; MIDIEndpointRef endpoint; MIDIEndpointRef destinationId; unsigned long long lastTime; }; // ****** // API: OS-X // helper functions // ***** // coreMIDI port naming helper function /* This wraps up the code to take a passed-in endpoint and work out a nice human-readable name for it. For the moment, this function will return firstly the device name + port name, or if we can work out what external devices are hooked in, that name. It only grabs the very first connected device name. NB. won't get connected devices correctly before 10.3. */ static void readable_name(MIDIEndpointRef end, char *buffer, int bufsize) { MIDIEntityRef ent = NULL; MIDIDeviceRef dev = NULL; int ii, count, length, ret; SInt32 *idarray; CFDataRef data = NULL; CFStringRef s; buffer[0] = '\0'; if( MIDIObjectGetDataProperty(end, kMIDIPropertyConnectionUniqueID, &data) == 0) { length = CFDataGetLength(data) / sizeof(SInt32); idarray = (SInt32 *) CFDataGetBytePtr(data); count = 0; for (ii = 0; ii < length; ii++) { if (bufsize < 3) break; if (count > 0) { strcpy(buffer, ", "); buffer += 2; bufsize -= 2; } if (get_device_name(idarray[ii], buffer, bufsize) == 0) { count++; bufsize -= strlen(buffer); buffer += strlen(buffer); } } CFRelease(data); if (count > 0) return; } char * mid = buffer; // build up the name of the enclosing device, if it can be found. if (MIDIEndpointGetEntity(end, &ent) == 0) { if (MIDIEntityGetDevice(ent, &dev) == 0) { if (MIDIObjectGetStringProperty(dev, kMIDIPropertyName, &s) == 0) { CFStringGetCString(s, buffer, bufsize, 0); bufsize -= strlen(buffer) + 1; buffer += strlen(buffer); CFRelease(s); } } } // ge char buffy[128]; // Now add the port/endpoint name. // no need to update buffer pointer. Last item. if (MIDIObjectGetStringProperty(end, kMIDIPropertyName, &s) == 0) { CFStringGetCString(s, buffy, 128, 0); CFRelease(s); // copy if different if( strcmp( mid, buffy ) && strlen(buffy) < bufsize ) { *buffer = ' '; buffer++; strcpy( buffer, buffy ); } } } // port naming helper function (External devices) /* Uses the midiojectfindbyuniqueid function to hunt down the relevant device and copies its name into the buffer provided. We don't know what type of device we'll get back, so we first throw away any external flags (We don't care), and then cast it up to device which is the thing which has a useful name. If it can't find one, return -1. 0 returned on success. */ static int get_device_name(SInt32 uniqueid, char *buffer, int bufsize) { int ret; void *object; MIDIObjectType type; MIDIDeviceRef dev = NULL; MIDIEntityRef ent = NULL; MIDIEndpointRef end = NULL; CFStringRef name = NULL; ret = MIDIObjectFindByUniqueID(uniqueid, &object, &type); if (ret < 0) return -1; // now clear any external flag. if (type > 0) type = type & (~kMIDIObjectType_ExternalMask); if (type == kMIDIObjectType_Device) { dev = (MIDIDeviceRef) object; } else if (type == kMIDIObjectType_Entity) { ent = (MIDIEntityRef) object; if (MIDIEntityGetDevice(ent, &dev)) { return -1; } } if (type == kMIDIObjectType_Source || type == kMIDIObjectType_Destination) { end = (MIDIEndpointRef) object; if (MIDIEndpointGetEntity(end, &ent)) { return -1; } if (MIDIEntityGetDevice(ent, &dev)) { return -1; } } else { // unknown type printf("Unknown type %d returned from findobject\n", (int) type); CFRelease(object); return -1; } MIDIObjectGetStringProperty(dev, kMIDIPropertyName, &name); CFStringGetCString(name, buffer, bufsize, 0); CFRelease(name); return 0; } //*********************************************************************// // API: OS-X // Class Definitions: RtMidiIn //*********************************************************************// void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef ) { RtMidiIn::RtMidiInData *data = static_cast (procRef); CoreMidiData *apiData = static_cast (data->apiData); bool continueSysex = false; unsigned char status; unsigned short nBytes, iByte, size; unsigned long long time; RtMidiIn::MidiMessage message; const MIDIPacket *packet = &list->packet[0]; for ( unsigned int i=0; inumPackets; ++i ) { // My interpretation of the CoreMIDI documentation: all message // types, except sysex, are complete within a packet and there may // be several of them in a single packet. Sysex messages can be // broken across multiple packets but are bundled alone within a // packet. I'm assuming that sysex messages, if segmented, must // be complete within the same MIDIPacketList. nBytes = packet->length; if ( nBytes == 0 ) continue; // Calculate time stamp. message.timeStamp = 0.0; if ( data->firstMessage ) data->firstMessage = false; else { time = packet->timeStamp; time -= apiData->lastTime; time = AudioConvertHostTimeToNanos( time ); message.timeStamp = time * 0.000000001; } apiData->lastTime = packet->timeStamp; iByte = 0; if ( continueSysex ) { // We have a continuing, segmented sysex message. if ( !(data->ignoreFlags & 0x01) ) { // If we're not ignoring sysex messages, copy the entire packet. for ( unsigned int j=0; jdata[j] ); } if ( packet->data[nBytes] == 0xF7 ) continueSysex = false; if ( !continueSysex ) { // If not a continuing sysex message, invoke the user callback function or queue the message. if ( data->usingCallback && message.bytes.size() > 0 ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( message.timeStamp, &message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } message.bytes.clear(); } } else { while ( iByte < nBytes ) { size = 0; // We are expecting that the next byte in the packet is a status byte. status = packet->data[iByte]; if ( !(status & 0x80) ) break; // Determine the number of bytes in the MIDI message. if ( status < 0xC0 ) size = 3; else if ( status < 0xE0 ) size = 2; else if ( status < 0xF0 ) size = 3; else if ( status == 0xF0 ) { // A MIDI sysex if ( data->ignoreFlags & 0x01 ) { size = 0; iByte = nBytes; } else size = nBytes - iByte; if ( packet->data[nBytes] == 0xF7 ) continueSysex = false; } else if ( status < 0xF3 ) { if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) { // A MIDI time code message and we're ignoring it. size = 0; iByte += 3; } else size = 3; } else if ( status == 0xF3 ) size = 2; else if ( status == 0xF8 ) { size = 1; if ( data->ignoreFlags & 0x02 ) { // A MIDI timing tick message and we're ignoring it. size = 0; iByte += 3; } } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { // A MIDI active sensing message and we're ignoring it. size = 0; iByte += 1; } else size = 1; // Copy the MIDI data to our vector. if ( size ) { message.bytes.assign( &packet->data[iByte], &packet->data[iByte+size] ); if ( !continueSysex ) { // If not a continuing sysex message, invoke the user callback function or queue the message. if ( data->usingCallback ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( message.timeStamp, &message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } message.bytes.clear(); } iByte += size; } } } packet = MIDIPacketNext(packet); } } void RtMidiIn :: initialize( void ) { // Set up our client. MIDIClientRef client; OSStatus result = MIDIClientCreate( CFSTR("RtMidi Input Client"), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "RtMidiIn::initialize: error creating OS-X MIDI client object."; error( RtError::DRIVER_ERROR ); } // Save our api-specific connection information. CoreMidiData *data = (CoreMidiData *) new CoreMidiData; data->client = client; data->endpoint = 0; apiData_ = (void *) data; inputData_.apiData = (void *) data; } void RtMidiIn :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nSrc = MIDIGetNumberOfSources(); if (nSrc < 1) { errorString_ = "RtMidiIn::openPort: no MIDI input sources found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nSrc ) { ost << "RtMidiIn::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIInputPortCreate( data->client, CFSTR("RtMidi MIDI Input Port"), midiInputCallback, (void *)&inputData_, &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "RtMidiIn::openPort: error creating OS-X MIDI input port."; error( RtError::DRIVER_ERROR ); } // Get the desired input source identifier. MIDIEndpointRef endpoint = MIDIGetSource( portNumber ); if ( endpoint == NULL ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "RtMidiIn::openPort: error getting MIDI input source reference."; error( RtError::DRIVER_ERROR ); } // Make the connection. result = MIDIPortConnectSource( port, endpoint, NULL ); if ( result != noErr ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "RtMidiIn::openPort: error connecting OS-X MIDI input port."; error( RtError::DRIVER_ERROR ); } // Save our api-specific port information. data->port = port; connected_ = true; } void RtMidiIn :: openVirtualPort() { CoreMidiData *data = static_cast (apiData_); // Create a virtual MIDI input destination. MIDIEndpointRef endpoint; OSStatus result = MIDIDestinationCreate( data->client, CFSTR("RtMidi Input"), midiInputCallback, (void *)&inputData_, &endpoint ); if ( result != noErr ) { errorString_ = "RtMidiIn::openVirtualPort: error creating virtual OS-X MIDI destination."; error( RtError::DRIVER_ERROR ); } // Save our api-specific connection information. data->endpoint = endpoint; } void RtMidiIn :: closePort( void ) { if ( connected_ ) { CoreMidiData *data = static_cast (apiData_); MIDIPortDispose( data->port ); connected_ = false; } } RtMidiIn :: ~RtMidiIn() { // Close a connection if it exists. closePort(); // Cleanup. CoreMidiData *data = static_cast (apiData_); MIDIClientDispose( data->client ); if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); delete data; } unsigned int RtMidiIn :: getPortCount() { return MIDIGetNumberOfSources(); } std::string RtMidiIn :: getPortName( unsigned int portNumber ) { CFStringRef nameRef; MIDIEndpointRef portRef; std::ostringstream ost; char name[128]; if ( portNumber >= MIDIGetNumberOfSources() ) { ost << "RtMidiIn::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } portRef = MIDIGetSource( portNumber ); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 readable_name(portRef, name, sizeof(name)); #else MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef ); CFStringGetCString( nameRef, name, sizeof(name), 0); CFRelease( nameRef ); #endif std::string stringName = name; return stringName; } //*********************************************************************// // API: OS-X // Class Definitions: RtMidiOut //*********************************************************************// unsigned int RtMidiOut :: getPortCount() { return MIDIGetNumberOfDestinations(); } std::string RtMidiOut :: getPortName( unsigned int portNumber ) { CFStringRef nameRef; MIDIEndpointRef portRef; std::ostringstream ost; char name[128]; if ( portNumber >= MIDIGetNumberOfDestinations() ) { ost << "RtMidiOut::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } portRef = MIDIGetDestination( portNumber ); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 readable_name(portRef, name, sizeof(name)); #else MIDIObjectGetStringProperty( portRef, kMIDIPropertyName, &nameRef ); CFStringGetCString( nameRef, name, sizeof(name), 0); CFRelease( nameRef ); #endif std::string stringName = name; return stringName; } void RtMidiOut :: initialize( void ) { // Set up our client. MIDIClientRef client; OSStatus result = MIDIClientCreate( CFSTR("RtMidi Output Client"), NULL, NULL, &client ); if ( result != noErr ) { errorString_ = "RtMidiOut::initialize: error creating OS-X MIDI client object."; error( RtError::DRIVER_ERROR ); } // Save our api-specific connection information. CoreMidiData *data = (CoreMidiData *) new CoreMidiData; data->client = client; data->endpoint = 0; apiData_ = (void *) data; } void RtMidiOut :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nDest = MIDIGetNumberOfDestinations(); if (nDest < 1) { errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nDest ) { ost << "RtMidiOut::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } MIDIPortRef port; CoreMidiData *data = static_cast (apiData_); OSStatus result = MIDIOutputPortCreate( data->client, CFSTR("RtMidi Virtual MIDI Output Port"), &port ); if ( result != noErr ) { MIDIClientDispose( data->client ); errorString_ = "RtMidiOut::openPort: error creating OS-X MIDI output port."; error( RtError::DRIVER_ERROR ); } // Get the desired output port identifier. MIDIEndpointRef destination = MIDIGetDestination( portNumber ); if ( destination == NULL ) { MIDIPortDispose( port ); MIDIClientDispose( data->client ); errorString_ = "RtMidiOut::openPort: error getting MIDI output destination reference."; error( RtError::DRIVER_ERROR ); } // Save our api-specific connection information. data->port = port; data->destinationId = destination; connected_ = true; } void RtMidiOut :: closePort( void ) { if ( connected_ ) { CoreMidiData *data = static_cast (apiData_); MIDIPortDispose( data->port ); connected_ = false; } } void RtMidiOut :: openVirtualPort() { CoreMidiData *data = static_cast (apiData_); if ( data->endpoint ) { errorString_ = "RtMidiOut::openVirtualPort: a virtual output port already exists!"; error( RtError::WARNING ); return; } // Create a virtual MIDI output source. MIDIEndpointRef endpoint; OSStatus result = MIDISourceCreate( data->client, CFSTR("RtMidi Output"), &endpoint ); if ( result != noErr ) { errorString_ = "RtMidiOut::initialize: error creating OS-X virtual MIDI source."; error( RtError::DRIVER_ERROR ); } // Save our api-specific connection information. data->endpoint = endpoint; } RtMidiOut :: ~RtMidiOut() { // Close a connection if it exists. closePort(); // Cleanup. CoreMidiData *data = static_cast (apiData_); MIDIClientDispose( data->client ); if ( data->endpoint ) MIDIEndpointDispose( data->endpoint ); delete data; } void RtMidiOut :: sendMessage( std::vector *message ) { unsigned int nBytes = message->size(); // Pad the buffer for extra (unknown) structure data. Byte buffer[nBytes+32]; MIDIPacketList *pktlist = (MIDIPacketList *) buffer; MIDIPacket *curPacket = MIDIPacketListInit( pktlist ); MIDITimeStamp timeStamp = 0; curPacket = MIDIPacketListAdd( pktlist, sizeof(buffer), curPacket, timeStamp, nBytes, &message->at(0) ); CoreMidiData *data = static_cast (apiData_); // Send to any destinations that may have connected to us. OSStatus result; if ( data->endpoint ) { result = MIDIReceived( data->endpoint, pktlist ); if ( result != noErr ) { errorString_ = "RtMidiOut::sendMessage: error sending MIDI to virtual destinations."; error( RtError::WARNING ); } } // And send to an explicit destination port if we're connected. if ( connected_ ) { result = MIDISend( data->port, data->destinationId, pktlist ); if ( result != noErr ) { errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port."; error( RtError::WARNING ); } } } #endif // __MACOSX_CORE__ //*********************************************************************// // API: LINUX ALSA SEQUENCER //*********************************************************************// // API information found at: // - http://www.alsa-project.org/documentation.php#Library // chuck #if defined(__LINUX_ALSASEQ__) || defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) // The ALSA Sequencer API is based on the use of a callback function for // MIDI input. // // Thanks to Pedro Lopez-Cabanillas for help with the ALSA sequencer // time stamps and other assorted fixes!!! #include #include // ALSA header file. #include // A structure to hold variables related to the ALSA API // implementation. struct AlsaMidiData { snd_seq_t *seq; int vport; snd_seq_port_subscribe_t *subscription; snd_midi_event_t *coder; unsigned int bufferSize; unsigned char *buffer; pthread_t thread; unsigned long long lastTime; int queue_id; // an input queue is needed to get timestamped events }; #define PORT_TYPE( pinfo, bits ) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits)) //*********************************************************************// // API: LINUX ALSA // Class Definitions: RtMidiIn //*********************************************************************// extern "C" void *alsaMidiHandler( void *ptr ) { RtMidiIn::RtMidiInData *data = static_cast (ptr); AlsaMidiData *apiData = static_cast (data->apiData); long nBytes; unsigned long long time, lastTime; bool continueSysex = false; RtMidiIn::MidiMessage message; snd_seq_event_t *ev; int result; apiData->bufferSize = 32; result = snd_midi_event_new( 0, &apiData->coder ); if ( result < 0 ) { data->doInput = false; std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing MIDI event parser!\n\n"; return 0; } unsigned char *buffer = (unsigned char *) malloc( apiData->bufferSize ); if ( buffer == NULL ) { data->doInput = false; std::cerr << "\nRtMidiIn::alsaMidiHandler: error initializing buffer memory!\n\n"; return 0; } snd_midi_event_init( apiData->coder ); snd_midi_event_no_status( apiData->coder, 1 ); // suppress running status messages while ( data->doInput ) { if ( snd_seq_event_input_pending( apiData->seq, 1 ) == 0 ) { // No data pending ... sleep a bit. usleep( 1000 ); continue; } // If here, there should be data. result = snd_seq_event_input( apiData->seq, &ev ); if ( result == -ENOSPC ) { std::cerr << "\nRtMidiIn::alsaMidiHandler: MIDI input buffer overrun!\n\n"; continue; } else if ( result <= 0 ) { std::cerr << "RtMidiIn::alsaMidiHandler: unknown MIDI input error!\n"; continue; } // This is a bit weird, but we now have to decode an ALSA MIDI // event (back) into MIDI bytes. We'll ignore non-MIDI types. message.bytes.clear(); switch ( ev->type ) { case SND_SEQ_EVENT_PORT_SUBSCRIBED: #if defined(__RTMIDI_DEBUG__) std::cout << "RtMidiIn::alsaMidiHandler: port connection made!\n"; #endif break; case SND_SEQ_EVENT_PORT_UNSUBSCRIBED: std::cerr << "RtMidiIn::alsaMidiHandler: port connection has closed!\n"; data->doInput = false; break; case SND_SEQ_EVENT_QFRAME: // MIDI time code if ( data->ignoreFlags & 0x02 ) break; case SND_SEQ_EVENT_TICK: // MIDI timing tick if ( data->ignoreFlags & 0x02 ) break; case SND_SEQ_EVENT_SENSING: // Active sensing if ( data->ignoreFlags & 0x04 ) break; case SND_SEQ_EVENT_SYSEX: if ( (data->ignoreFlags & 0x01) ) break; if ( ev->data.ext.len > apiData->bufferSize ) { apiData->bufferSize = ev->data.ext.len; free( buffer ); buffer = (unsigned char *) malloc( apiData->bufferSize ); if ( buffer == NULL ) { data->doInput = false; std::cerr << "\nRtMidiIn::alsaMidiHandler: error resizing buffer memory!\n\n"; break; } } default: nBytes = snd_midi_event_decode( apiData->coder, buffer, apiData->bufferSize, ev ); if ( nBytes <= 0 ) { #if defined(__RTMIDI_DEBUG__) std::cerr << "\nRtMidiIn::alsaMidiHandler: event parsing error or not a MIDI event!\n\n"; #endif break; } // The ALSA sequencer has a maximum buffer size for MIDI sysex // events of 256 bytes. If a device sends sysex messages larger // than this, they are segmented into 256 byte chunks. So, // we'll watch for this and concatenate sysex chunks into a // single sysex message if necessary. if ( !continueSysex ) message.bytes.assign( buffer, &buffer[nBytes] ); else message.bytes.insert( message.bytes.end(), buffer, &buffer[nBytes] ); if ( ev->type == SND_SEQ_EVENT_SYSEX && message.bytes.back() == 0xF7 ) continueSysex = false; else { continueSysex = true; break; } // Calculate the time stamp: message.timeStamp = 0.0; // Method 1: Use the system time. //(void)gettimeofday(&tv, (struct timezone *)NULL); //time = (tv.tv_sec * 1000000) + tv.tv_usec; // Method 2: Use the ALSA sequencer event time data. // (thanks to Pedro Lopez-Cabanillas!). time = ( ev->time.time.tv_sec * 1000000 ) + ( ev->time.time.tv_nsec/1000 ); lastTime = time; time -= apiData->lastTime; apiData->lastTime = lastTime; if ( data->firstMessage == true ) data->firstMessage = false; else message.timeStamp = time * 0.000001; } snd_seq_free_event(ev); if ( message.bytes.size() == 0 ) continue; if ( data->usingCallback ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( message.timeStamp, &message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } } if ( buffer ) free( buffer ); snd_midi_event_free( apiData->coder ); apiData->coder = 0; return 0; } void RtMidiIn :: initialize( void ) { // Set up the ALSA sequencer client. snd_seq_t *seq; int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); if ( result < 0 ) { errorString_ = "RtMidiIn::initialize: error creating ALSA sequencer input client object."; error( RtError::DRIVER_ERROR ); } // Set client name. snd_seq_set_client_name(seq, "RtMidi Input Client"); // Save our api-specific connection information. AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; data->seq = seq; data->vport = -1; apiData_ = (void *) data; inputData_.apiData = (void *) data; // Create the input queue data->queue_id = snd_seq_alloc_named_queue(seq, "RtMidi Queue"); // Set arbitrary tempo (mm=100) and resolution (240) snd_seq_queue_tempo_t *qtempo; snd_seq_queue_tempo_alloca(&qtempo); snd_seq_queue_tempo_set_tempo(qtempo, 600000); snd_seq_queue_tempo_set_ppq(qtempo, 240); snd_seq_set_queue_tempo(data->seq, data->queue_id, qtempo); snd_seq_drain_output(data->seq); } // This function is used to count or get the pinfo structure for a given port number. unsigned int portInfo( snd_seq_t *seq, snd_seq_port_info_t *pinfo, unsigned int type, int portNumber ) { snd_seq_client_info_t *cinfo; int client; int count = 0; snd_seq_client_info_alloca( &cinfo ); snd_seq_client_info_set_client( cinfo, -1 ); while ( snd_seq_query_next_client( seq, cinfo ) >= 0 ) { client = snd_seq_client_info_get_client( cinfo ); if ( client == 0 ) continue; // Reset query info snd_seq_port_info_set_client( pinfo, client ); snd_seq_port_info_set_port( pinfo, -1 ); while ( snd_seq_query_next_port( seq, pinfo ) >= 0 ) { if ( !PORT_TYPE( pinfo, type ) ) continue; if ( count == portNumber ) return 1; count++; } } // If a negative portNumber was used, return the port count. if ( portNumber < 0 ) return count; return 0; } void RtMidiIn :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { errorString_ = "RtMidiIn::openPort: no MIDI input sources found!"; error( RtError::NO_DEVICES_FOUND ); } snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); std::ostringstream ost; AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) == 0 ) { ost << "RtMidiIn::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } snd_seq_addr_t sender, receiver; sender.client = snd_seq_port_info_get_client( pinfo ); sender.port = snd_seq_port_info_get_port( pinfo ); receiver.client = snd_seq_client_id( data->seq ); if ( data->vport < 0 ) { snd_seq_port_info_set_client( pinfo, 0 ); snd_seq_port_info_set_port( pinfo, 0 ); snd_seq_port_info_set_capability( pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ); snd_seq_port_info_set_type( pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); snd_seq_port_info_set_midi_channels(pinfo, 16); snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); snd_seq_port_info_set_name(pinfo, "RtMidi Input"); data->vport = snd_seq_create_port(data->seq, pinfo); if ( data->vport < 0 ) { errorString_ = "RtMidiIn::openPort: ALSA error creating input port."; error( RtError::DRIVER_ERROR ); } } receiver.port = data->vport; // Make subscription snd_seq_port_subscribe_malloc( &data->subscription ); snd_seq_port_subscribe_set_sender(data->subscription, &sender); snd_seq_port_subscribe_set_dest(data->subscription, &receiver); if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { errorString_ = "RtMidiIn::openPort: ALSA error making port connection."; error( RtError::DRIVER_ERROR ); } if ( inputData_.doInput == false ) { // Start the input queue snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); // Start our MIDI input thread. pthread_attr_t attr; pthread_attr_init(&attr); // chuck //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //pthread_attr_setschedpolicy(&attr, SCHED_OTHER); inputData_.doInput = true; int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); pthread_attr_destroy(&attr); if (err) { snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); inputData_.doInput = false; errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!"; error( RtError::THREAD_ERROR ); } } connected_ = true; } void RtMidiIn :: openVirtualPort() { AlsaMidiData *data = static_cast (apiData_); if ( data->vport < 0 ) { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); snd_seq_port_info_set_capability( pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE ); snd_seq_port_info_set_type( pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION ); snd_seq_port_info_set_midi_channels(pinfo, 16); snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, data->queue_id); snd_seq_port_info_set_name(pinfo, "RtMidi Input"); data->vport = snd_seq_create_port(data->seq, pinfo); if ( data->vport < 0 ) { errorString_ = "RtMidiIn::openVirtualPort: ALSA error creating virtual port."; error( RtError::DRIVER_ERROR ); } } if ( inputData_.doInput == false ) { // Start the input queue snd_seq_start_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); // Start our MIDI input thread. pthread_attr_t attr; pthread_attr_init(&attr); // chuck //pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); //pthread_attr_setschedpolicy(&attr, SCHED_OTHER); inputData_.doInput = true; int err = pthread_create(&data->thread, &attr, alsaMidiHandler, &inputData_); pthread_attr_destroy(&attr); if (err) { snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); inputData_.doInput = false; errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!"; error( RtError::THREAD_ERROR ); } } } void RtMidiIn :: closePort( void ) { if ( connected_ ) { AlsaMidiData *data = static_cast (apiData_); snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); // Stop the input queue snd_seq_stop_queue( data->seq, data->queue_id, NULL ); snd_seq_drain_output( data->seq ); connected_ = false; } } RtMidiIn :: ~RtMidiIn() { // Close a connection if it exists. closePort(); // Shutdown the input thread. AlsaMidiData *data = static_cast (apiData_); if ( inputData_.doInput ) { inputData_.doInput = false; pthread_join( data->thread, NULL ); } // Cleanup. if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); snd_seq_free_queue( data->seq, data->queue_id ); snd_seq_close( data->seq ); delete data; } unsigned int RtMidiIn :: getPortCount() { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, -1 ); } std::string RtMidiIn :: getPortName( unsigned int portNumber ) { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, (int) portNumber ) ) { std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) ); return stringName; } // If we get here, we didn't find a match. errorString_ = "RtMidiIn::getPortName: error looking for port name!"; error( RtError::INVALID_PARAMETER ); return 0; } //*********************************************************************// // API: LINUX ALSA // Class Definitions: RtMidiOut //*********************************************************************// unsigned int RtMidiOut :: getPortCount() { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); return portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, -1 ); } std::string RtMidiOut :: getPortName( unsigned int portNumber ) { snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) ) { std::string stringName = std::string( snd_seq_port_info_get_name( pinfo ) ); return stringName; } // If we get here, we didn't find a match. errorString_ = "RtMidiOut::getPortName: error looking for port name!"; error( RtError::INVALID_PARAMETER ); return 0; } void RtMidiOut :: initialize( void ) { // Set up the ALSA sequencer client. snd_seq_t *seq; int result = snd_seq_open(&seq, "default", SND_SEQ_OPEN_OUTPUT, 0); if ( result < 0 ) { errorString_ = "RtMidiOut::initialize: error creating ALSA sequencer client object."; error( RtError::DRIVER_ERROR ); } // Set client name. snd_seq_set_client_name(seq, "RtMidi Output Client"); // Save our api-specific connection information. AlsaMidiData *data = (AlsaMidiData *) new AlsaMidiData; data->seq = seq; data->vport = -1; data->bufferSize = 32; data->coder = 0; data->buffer = 0; result = snd_midi_event_new( data->bufferSize, &data->coder ); if ( result < 0 ) { delete data; errorString_ = "RtMidiOut::initialize: error initializing MIDI event parser!\n\n"; error( RtError::DRIVER_ERROR ); } data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { delete data; errorString_ = "RtMidiOut::initialize: error allocating buffer memory!\n\n"; error( RtError::MEMORY_ERROR ); } snd_midi_event_init( data->coder ); apiData_ = (void *) data; } void RtMidiOut :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nSrc = this->getPortCount(); if (nSrc < 1) { errorString_ = "RtMidiOut::openPort: no MIDI output sources found!"; error( RtError::NO_DEVICES_FOUND ); } snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca( &pinfo ); std::ostringstream ost; AlsaMidiData *data = static_cast (apiData_); if ( portInfo( data->seq, pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, (int) portNumber ) == 0 ) { ost << "RtMidiOut::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } snd_seq_addr_t sender, receiver; receiver.client = snd_seq_port_info_get_client( pinfo ); receiver.port = snd_seq_port_info_get_port( pinfo ); sender.client = snd_seq_client_id( data->seq ); if ( data->vport < 0 ) { data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC ); if ( data->vport < 0 ) { errorString_ = "RtMidiOut::openPort: ALSA error creating output port."; error( RtError::DRIVER_ERROR ); } } sender.port = data->vport; // Make subscription snd_seq_port_subscribe_malloc( &data->subscription ); snd_seq_port_subscribe_set_sender(data->subscription, &sender); snd_seq_port_subscribe_set_dest(data->subscription, &receiver); snd_seq_port_subscribe_set_time_update(data->subscription, 1); snd_seq_port_subscribe_set_time_real(data->subscription, 1); if ( snd_seq_subscribe_port(data->seq, data->subscription) ) { errorString_ = "RtMidiOut::openPort: ALSA error making port connection."; error( RtError::DRIVER_ERROR ); } connected_ = true; } void RtMidiOut :: closePort( void ) { if ( connected_ ) { AlsaMidiData *data = static_cast (apiData_); snd_seq_unsubscribe_port( data->seq, data->subscription ); snd_seq_port_subscribe_free( data->subscription ); connected_ = false; } } void RtMidiOut :: openVirtualPort() { AlsaMidiData *data = static_cast (apiData_); if ( data->vport < 0 ) { data->vport = snd_seq_create_simple_port( data->seq, "RtMidi Output", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_MIDI_GENERIC ); if ( data->vport < 0 ) { errorString_ = "RtMidiOut::openVirtualPort: ALSA error creating virtual port."; error( RtError::DRIVER_ERROR ); } } } RtMidiOut :: ~RtMidiOut() { // Close a connection if it exists. closePort(); // Cleanup. AlsaMidiData *data = static_cast (apiData_); if ( data->vport >= 0 ) snd_seq_delete_port( data->seq, data->vport ); if ( data->coder ) snd_midi_event_free( data->coder ); if ( data->buffer ) free( data->buffer ); snd_seq_close( data->seq ); delete data; } void RtMidiOut :: sendMessage( std::vector *message ) { int result; AlsaMidiData *data = static_cast (apiData_); unsigned int nBytes = message->size(); if ( nBytes > data->bufferSize ) { data->bufferSize = nBytes; result = snd_midi_event_resize_buffer ( data->coder, nBytes); if ( result != 0 ) { errorString_ = "RtMidiOut::sendMessage: ALSA error resizing MIDI event buffer."; error( RtError::DRIVER_ERROR ); } free (data->buffer); data->buffer = (unsigned char *) malloc( data->bufferSize ); if ( data->buffer == NULL ) { errorString_ = "RtMidiOut::initialize: error allocating buffer memory!\n\n"; error( RtError::MEMORY_ERROR ); } } snd_seq_event_t ev; snd_seq_ev_clear(&ev); snd_seq_ev_set_source(&ev, data->vport); snd_seq_ev_set_subs(&ev); snd_seq_ev_set_direct(&ev); for ( unsigned int i=0; ibuffer[i] = message->at(i); result = snd_midi_event_encode( data->coder, data->buffer, (long)nBytes, &ev ); if ( result < (int)nBytes ) { errorString_ = "RtMidiOut::sendMessage: event parsing error!"; error( RtError::WARNING ); return; } // Send the event. result = snd_seq_event_output(data->seq, &ev); if ( result < 0 ) { errorString_ = "RtMidiOut::sendMessage: error sending MIDI message to port."; error( RtError::WARNING ); } snd_seq_drain_output(data->seq); } #endif // __LINUX_ALSA__ //*********************************************************************// // API: IRIX MD //*********************************************************************// // API information gleamed from: // http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?cmd=getdoc&coll=0650&db=man&fname=3%20mdIntro // If the Makefile doesn't work, try the following: // CC -o midiinfo -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp midiinfo.cpp -lpthread -lmd // CC -o midiout -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp midiout.cpp -lpthread -lmd // CC -o qmidiin -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp qmidiin.cpp -lpthread -lmd // CC -o cmidiin -LANG:std -D__IRIX_MD__ -I../ ../RtMidi.cpp cmidiin.cpp -lpthread -lmd #if defined(__IRIX_MD__) #include #include #include // Irix MIDI header file. #include // A structure to hold variables related to the IRIX API // implementation. struct IrixMidiData { MDport port; pthread_t thread; }; //*********************************************************************// // API: IRIX // Class Definitions: RtMidiIn //*********************************************************************// extern "C" void *irixMidiHandler( void *ptr ) { RtMidiIn::RtMidiInData *data = static_cast (ptr); IrixMidiData *apiData = static_cast (data->apiData); bool continueSysex = false; unsigned char status; unsigned short size; MDevent event; int fd = mdGetFd( apiData->port ); if ( fd < 0 ) { data->doInput = false; std::cerr << "\nRtMidiIn::irixMidiHandler: error getting port descriptor!\n\n"; return 0; } fd_set mask, rmask; FD_ZERO( &mask ); FD_SET( fd, &mask ); struct timeval timeout = {0, 0}; RtMidiIn::MidiMessage message; int result; while ( data->doInput ) { rmask = mask; timeout.tv_sec = 0; timeout.tv_usec = 0; if ( select( fd+1, &rmask, NULL, NULL, &timeout ) <= 0 ) { // No data pending ... sleep a bit. usleep( 1000 ); continue; } // If here, there should be data. result = mdReceive( apiData->port, &event, 1); if ( result <= 0 ) { std::cerr << "\nRtMidiIn::irixMidiHandler: MIDI input read error!\n\n"; continue; } message.timeStamp = event.stamp * 0.000000001; size = 0; status = event.msg[0]; if ( !(status & 0x80) ) continue; if ( status == 0xF0 ) { // Sysex message ... can be segmented across multiple messages. if ( !(data->ignoreFlags & 0x01) ) { if ( continueSysex ) { // We have a continuing, segmented sysex message. Append // the new bytes to our existing message. for ( int i=0; iusingCallback && message.bytes.size() > 0 ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( message.timeStamp, &message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } message.bytes.clear(); } } } mdFree( NULL ); continue; } else if ( status < 0xC0 ) size = 3; else if ( status < 0xE0 ) size = 2; else if ( status < 0xF0 ) size = 3; else if ( status < 0xF3 ) { if ( status == 0xF1 && !(data->ignoreFlags & 0x02) ) { // A MIDI time code message and we're not ignoring it. size = 3; } } else if ( status == 0xF3 ) size = 2; else if ( status == 0xF8 ) { if ( !(data->ignoreFlags & 0x02) ) { // A MIDI timing tick message and we're not ignoring it. size = 1; } } else if ( status == 0xFE ) { // MIDI active sensing if ( !(data->ignoreFlags & 0x04) ) size = 1; } else size = 1; // Copy the MIDI data to our vector. if ( size ) { message.bytes.assign( &event.msg[0], &event.msg[size] ); // Invoke the user callback function or queue the message. if ( data->usingCallback ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( message.timeStamp, &message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } message.bytes.clear(); } } return 0; } void RtMidiIn :: initialize( void ) { // Initialize the Irix MIDI system. At the moment, we will not // worry about a return value of zero (ports) because there is a // chance the user could plug something in after instantiation. int nPorts = mdInit(); // Create our api-specific connection information. IrixMidiData *data = (IrixMidiData *) new IrixMidiData; apiData_ = (void *) data; inputData_.apiData = (void *) data; } void RtMidiIn :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } int nPorts = mdInit(); if (nPorts < 1) { errorString_ = "RtMidiIn::openPort: no Irix MIDI input sources found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nPorts ) { ost << "RtMidiIn::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } IrixMidiData *data = static_cast (apiData_); data->port = mdOpenInPort( mdGetName(portNumber) ); if ( data->port == NULL ) { ost << "RtMidiIn::openPort: Irix error opening the port (" << portNumber << ")."; errorString_ = ost.str(); error( RtError::DRIVER_ERROR ); } mdSetStampMode(data->port, MD_DELTASTAMP); // Start our MIDI input thread. pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_attr_setschedpolicy(&attr, SCHED_RR); inputData_.doInput = true; int err = pthread_create(&data->thread, &attr, irixMidiHandler, &inputData_); pthread_attr_destroy(&attr); if (err) { mdClosePort( data->port ); inputData_.doInput = false; errorString_ = "RtMidiIn::openPort: error starting MIDI input thread!"; error( RtError::THREAD_ERROR ); } connected_ = true; } void RtMidiIn :: openVirtualPort() { // This function cannot be implemented for the Irix MIDI API. errorString_ = "RtMidiIn::openVirtualPort: cannot be implemented in Irix MIDI API!"; error( RtError::WARNING ); } void RtMidiIn :: closePort( void ) { if ( connected_ ) { IrixMidiData *data = static_cast (apiData_); mdClosePort( data->port ); connected_ = false; // Shutdown the input thread. inputData_.doInput = false; pthread_join( data->thread, NULL ); } } RtMidiIn :: ~RtMidiIn() { // Close a connection if it exists. closePort(); // Cleanup. IrixMidiData *data = static_cast (apiData_); delete data; } unsigned int RtMidiIn :: getPortCount() { int nPorts = mdInit(); if ( nPorts >= 0 ) return nPorts; else return 0; } std::string RtMidiIn :: getPortName( unsigned int portNumber ) { int nPorts = mdInit(); std::ostringstream ost; if ( portNumber >= nPorts ) { ost << "RtMidiIn::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } std::string stringName = std::string( mdGetName( portNumber ) ); return stringName; } //*********************************************************************// // API: IRIX MD // Class Definitions: RtMidiOut //*********************************************************************// unsigned int RtMidiOut :: getPortCount() { int nPorts = mdInit(); if ( nPorts >= 0 ) return nPorts; else return 0; } std::string RtMidiOut :: getPortName( unsigned int portNumber ) { int nPorts = mdInit(); std::ostringstream ost; if ( portNumber >= nPorts ) { ost << "RtMidiIn::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } std::string stringName = std::string( mdGetName( portNumber ) ); return stringName; } void RtMidiOut :: initialize( void ) { // Initialize the Irix MIDI system. At the moment, we will not // worry about a return value of zero (ports) because there is a // chance the user could plug something in after instantiation. int nPorts = mdInit(); // Create our api-specific connection information. IrixMidiData *data = (IrixMidiData *) new IrixMidiData; apiData_ = (void *) data; } void RtMidiOut :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } int nPorts = mdInit(); if (nPorts < 1) { errorString_ = "RtMidiOut::openPort: no Irix MIDI output sources found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nPorts ) { ost << "RtMidiOut::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } IrixMidiData *data = static_cast (apiData_); data->port = mdOpenOutPort( mdGetName(portNumber) ); if ( data->port == NULL ) { ost << "RtMidiOut::openPort: Irix error opening the port (" << portNumber << ")."; errorString_ = ost.str(); error( RtError::DRIVER_ERROR ); } mdSetStampMode(data->port, MD_NOSTAMP); connected_ = true; } void RtMidiOut :: closePort( void ) { if ( connected_ ) { IrixMidiData *data = static_cast (apiData_); mdClosePort( data->port ); connected_ = false; } } void RtMidiOut :: openVirtualPort() { // This function cannot be implemented for the Irix MIDI API. errorString_ = "RtMidiOut::openVirtualPort: cannot be implemented in Irix MIDI API!"; error( RtError::WARNING ); } RtMidiOut :: ~RtMidiOut() { // Close a connection if it exists. closePort(); // Cleanup. IrixMidiData *data = static_cast (apiData_); delete data; } void RtMidiOut :: sendMessage( std::vector *message ) { int result; MDevent event; IrixMidiData *data = static_cast (apiData_); char *buffer = 0; unsigned int nBytes = message->size(); if ( nBytes == 0 ) return; event.stamp = 0; if ( message->at(0) == 0xF0 ) { if ( nBytes < 3 ) return; // check for bogus sysex event.msg[0] = 0xF0; event.msglen = nBytes; buffer = (char *) malloc( nBytes ); for ( int i=0; iat(i); event.sysexmsg = buffer; } else { for ( int i=0; iat(i); } // Send the event. result = mdSend( data->port, &event, 1 ); if ( buffer ) free( buffer ); if ( result < 1 ) { errorString_ = "RtMidiOut::sendMessage: IRIX error sending MIDI message!"; error( RtError::WARNING ); return; } } #endif // __IRIX_MD__ //*********************************************************************// // API: Windows Multimedia Library (MM) //*********************************************************************// // API information deciphered from: // - http://msdn.microsoft.com/library/default.asp?url=/library/en-us/multimed/htm/_win32_midi_reference.asp // chuck #if defined(__WINDOWS_DS__) //#if defined(__WINDOWS_MM__) // The Windows MM API is based on the use of a callback function for // MIDI input. We convert the system specific time stamps to delta // time values. // Windows MM MIDI header files. #include #include // A structure to hold variables related to the CoreMIDI API // implementation. struct WinMidiData { HMIDIIN inHandle; // Handle to Midi Input Device HMIDIOUT outHandle; // Handle to Midi Output Device DWORD lastTime; RtMidiIn::MidiMessage message; }; //*********************************************************************// // API: Windows MM // Class Definitions: RtMidiIn //*********************************************************************// static void CALLBACK midiInputCallback( HMIDIOUT hmin, UINT inputStatus, DWORD instancePtr, DWORD midiMessage, DWORD timestamp ) { if ( inputStatus != MIM_DATA && inputStatus != MIM_LONGDATA ) return; //RtMidiIn::RtMidiInData *data = static_cast (instancePtr); RtMidiIn::RtMidiInData *data = (RtMidiIn::RtMidiInData *)instancePtr; WinMidiData *apiData = static_cast (data->apiData); // Calculate time stamp. apiData->message.timeStamp = 0.0; if ( data->firstMessage == true ) data->firstMessage = false; else apiData->message.timeStamp = (double) ( timestamp - apiData->lastTime ) * 0.001; apiData->lastTime = timestamp; if ( inputStatus == MIM_DATA ) { // Channel or system message // Make sure the first byte is a status byte. unsigned char status = (unsigned char) (midiMessage & 0x000000FF); if ( !(status & 0x80) ) return; // Determine the number of bytes in the MIDI message. unsigned short nBytes = 1; if ( status < 0xC0 ) nBytes = 3; else if ( status < 0xE0 ) nBytes = 2; else if ( status < 0xF0 ) nBytes = 3; else if ( status < 0xF3 ) { // A MIDI time code message and we're ignoring it. if ( status == 0xF1 && (data->ignoreFlags & 0x02) ) return; nBytes = 3; } else if ( status == 0xF3 ) nBytes = 2; else if ( status == 0xF8 && (data->ignoreFlags & 0x02) ) { // A MIDI timing tick message and we're ignoring it. return; } else if ( status == 0xFE && (data->ignoreFlags & 0x04) ) { // A MIDI active sensing message and we're ignoring it. return; } // Copy bytes to our MIDI message. unsigned char *ptr = (unsigned char *) &midiMessage; for ( int i=0; imessage.bytes.push_back( *ptr++ ); } else { // Sysex message MIDIHDR *sysex = ( MIDIHDR *) midiMessage; for ( int i=0; i<(int)sysex->dwBytesRecorded; i++ ) apiData->message.bytes.push_back( sysex->lpData[i] ); if ( apiData->message.bytes.back() != 0xF7 ) return; } if ( data->usingCallback ) { RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) data->userCallback; callback( apiData->message.timeStamp, &apiData->message.bytes, data->userData ); } else { // As long as we haven't reached our queue size limit, push the message. if ( data->queueLimit > data->queue.size() ) data->queue.push( apiData->message ); else std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n"; } // Clear the vector for the next input message. Note that doing // this here allows our code to work for sysex messages which are // segmented across multiple buffers. apiData->message.bytes.clear(); } void RtMidiIn :: initialize( void ) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plugin something later. unsigned int nDevices = midiInGetNumDevs(); if ( nDevices == 0 ) { errorString_ = "RtMidiIn::initialize: no MIDI input devices currently available."; error( RtError::WARNING ); } // Save our api-specific connection information. WinMidiData *data = (WinMidiData *) new WinMidiData; apiData_ = (void *) data; inputData_.apiData = (void *) data; data->message.bytes.clear(); // needs to be empty for first input message } void RtMidiIn :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiIn::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nDevices = midiInGetNumDevs(); if (nDevices == 0) { errorString_ = "RtMidiIn::openPort: no MIDI input sources found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nDevices ) { ost << "RtMidiIn::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } WinMidiData *data = static_cast (apiData_); MMRESULT result = midiInOpen( &data->inHandle, portNumber, (DWORD)&midiInputCallback, (DWORD)&inputData_, CALLBACK_FUNCTION ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "RtMidiIn::openPort: error creating Windows MM MIDI input port."; error( RtError::DRIVER_ERROR ); } result = midiInStart( data->inHandle ); if ( result != MMSYSERR_NOERROR ) { midiInClose( data->inHandle ); errorString_ = "RtMidiIn::openPort: error starting Windows MM MIDI input port."; error( RtError::DRIVER_ERROR ); } connected_ = true; } void RtMidiIn :: openVirtualPort() { // This function cannot be implemented for the Windows MM MIDI API. errorString_ = "RtMidiIn::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; error( RtError::WARNING ); } void RtMidiIn :: closePort( void ) { if ( connected_ ) { WinMidiData *data = static_cast (apiData_); midiInReset( data->inHandle ); midiInStop( data->inHandle ); midiInClose( data->inHandle ); connected_ = false; } } RtMidiIn :: ~RtMidiIn() { // Close a connection if it exists. closePort(); // Cleanup. WinMidiData *data = static_cast (apiData_); delete data; } unsigned int RtMidiIn :: getPortCount() { return midiInGetNumDevs(); } std::string RtMidiIn :: getPortName( unsigned int portNumber ) { unsigned int nDevices = midiInGetNumDevs(); if ( portNumber >= nDevices ) { std::ostringstream ost; ost << "RtMidiIn::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } MIDIINCAPS deviceCaps; MMRESULT result = midiInGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIINCAPS)); std::string stringName = std::string( deviceCaps.szPname ); return stringName; } //*********************************************************************// // API: Windows MM // Class Definitions: RtMidiOut //*********************************************************************// unsigned int RtMidiOut :: getPortCount() { return midiOutGetNumDevs(); } std::string RtMidiOut :: getPortName( unsigned int portNumber ) { unsigned int nDevices = midiOutGetNumDevs(); if ( portNumber >= nDevices ) { std::ostringstream ost; ost << "RtMidiOut::getPortName: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } MIDIOUTCAPS deviceCaps; MMRESULT result = midiOutGetDevCaps( portNumber, &deviceCaps, sizeof(MIDIOUTCAPS)); std::string stringName = std::string( deviceCaps.szPname ); return stringName; } void RtMidiOut :: initialize( void ) { // We'll issue a warning here if no devices are available but not // throw an error since the user can plug something in later. unsigned int nDevices = midiOutGetNumDevs(); if ( nDevices == 0 ) { errorString_ = "RtMidiOut::initialize: no MIDI output devices currently available."; error( RtError::WARNING ); } // Save our api-specific connection information. WinMidiData *data = (WinMidiData *) new WinMidiData; apiData_ = (void *) data; } void RtMidiOut :: openPort( unsigned int portNumber ) { if ( connected_ ) { errorString_ = "RtMidiOut::openPort: a valid connection already exists!"; error( RtError::WARNING ); return; } unsigned int nDevices = midiOutGetNumDevs(); if (nDevices < 1) { errorString_ = "RtMidiOut::openPort: no MIDI output destinations found!"; error( RtError::NO_DEVICES_FOUND ); } std::ostringstream ost; if ( portNumber >= nDevices ) { ost << "RtMidiOut::openPort: 'portNumber' argument (" << portNumber << ") is invalid."; errorString_ = ost.str(); error( RtError::INVALID_PARAMETER ); } WinMidiData *data = static_cast (apiData_); MMRESULT result = midiOutOpen( &data->outHandle, portNumber, (DWORD)NULL, (DWORD)NULL, CALLBACK_NULL ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "RtMidiOut::openPort: error creating Windows MM MIDI output port."; error( RtError::DRIVER_ERROR ); } connected_ = true; } void RtMidiOut :: closePort( void ) { if ( connected_ ) { WinMidiData *data = static_cast (apiData_); midiOutReset( data->outHandle ); midiOutClose( data->outHandle ); connected_ = false; } } void RtMidiOut :: openVirtualPort() { // This function cannot be implemented for the Windows MM MIDI API. errorString_ = "RtMidiOut::openVirtualPort: cannot be implemented in Windows MM MIDI API!"; error( RtError::WARNING ); } RtMidiOut :: ~RtMidiOut() { // Close a connection if it exists. closePort(); // Cleanup. WinMidiData *data = static_cast (apiData_); delete data; } void RtMidiOut :: sendMessage( std::vector *message ) { unsigned int nBytes = message->size(); if ( nBytes == 0 ) { errorString_ = "RtMidiOut::sendMessage: message argument is empty!"; error( RtError::WARNING ); return; } MMRESULT result; WinMidiData *data = static_cast (apiData_); if ( message->at(0) == 0xF0 ) { // Sysex message // Allocate buffer for sysex data. char *buffer = (char *) malloc( nBytes ); if ( buffer == NULL ) { errorString_ = "RtMidiOut::sendMessage: error allocating sysex message memory!"; error( RtError::MEMORY_ERROR ); } // Copy data to buffer. for ( unsigned int i=0; iat(i); // Create and prepare MIDIHDR structure. MIDIHDR sysex; sysex.lpData = (LPSTR) buffer; sysex.dwBufferLength = nBytes; sysex.dwFlags = 0; result = midiOutPrepareHeader( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { free( buffer ); errorString_ = "RtMidiOut::sendMessage: error preparing sysex header."; error( RtError::DRIVER_ERROR ); } // Send the message. result = midiOutLongMsg( data->outHandle, &sysex, sizeof(MIDIHDR) ); if ( result != MMSYSERR_NOERROR ) { free( buffer ); errorString_ = "RtMidiOut::sendMessage: error sending sysex message."; error( RtError::DRIVER_ERROR ); } // Unprepare the buffer and MIDIHDR. while ( MIDIERR_STILLPLAYING == midiOutUnprepareHeader( data->outHandle, &sysex, sizeof (MIDIHDR) ) ) Sleep( 1 ); free( buffer ); } else { // Channel or system message. // Make sure the message size isn't too big. if ( nBytes > 3 ) { errorString_ = "RtMidiOut::sendMessage: message size is greater than 3 bytes (and not sysex)!"; error( RtError::WARNING ); return; } // Pack MIDI bytes into double word. DWORD packet; unsigned char *ptr = (unsigned char *) &packet; for ( unsigned int i=0; iat(i); ptr++; } // Send the message immediately. result = midiOutShortMsg( data->outHandle, packet ); if ( result != MMSYSERR_NOERROR ) { errorString_ = "RtMidiOut::sendMessage: error sending MIDI message."; error( RtError::DRIVER_ERROR ); } } } #endif // __WINDOWS_MM__ #if defined(__LINUX_OSS__) // dummy /*void midiInputCallback( const MIDIPacketList *list, void *procRef, void *srcRef ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } */ void RtMidiIn :: initialize( void ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiIn :: openPort( unsigned int portNumber ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiIn :: openVirtualPort() { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiIn :: closePort( void ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } RtMidiIn :: ~RtMidiIn() { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } unsigned int RtMidiIn :: getPortCount() { return 0; } std::string RtMidiIn :: getPortName( unsigned int portNumber ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); return ""; } //*********************************************************************// // API: OS-X // Class Definitions: RtMidiOut //*********************************************************************// unsigned int RtMidiOut :: getPortCount() { return 0; } std::string RtMidiOut :: getPortName( unsigned int portNumber ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); return ""; } void RtMidiOut :: initialize( void ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiOut :: openPort( unsigned int portNumber ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiOut :: closePort( void ) { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } void RtMidiOut :: openVirtualPort() { fprintf( stderr, "[chuck](via rtmidi): midi not supported for this platform\n" ); } RtMidiOut :: ~RtMidiOut() { } void RtMidiOut :: sendMessage( std::vector *message ) { } #endif // dummy chuck-1.2.0.8.dfsg/src/rtmidi.h0000644000175000017500000002366310600421721014600 0ustar piempiem/**********************************************************************/ /*! \class RtMidi \brief An abstract base class for realtime MIDI input/output. This class implements some common functionality for the realtime MIDI input/output subclasses RtMidiIn and RtMidiOut. RtMidi WWW site: http://music.mcgill.ca/~gary/rtmidi/ RtMidi: realtime MIDI i/o C++ classes Copyright (c) 2003-2005 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**********************************************************************/ // RtMidi: Version 1.0.4, 14 October 2005 #ifndef RTMIDI_H #define RTMIDI_H #include "rterror.h" #include class RtMidi { public: //! Pure virtual openPort() function. virtual void openPort( unsigned int portNumber = 0 ) = 0; //! Pure virtual openVirtualPort() function. virtual void openVirtualPort() = 0; //! Pure virtual getPortCount() function. virtual unsigned int getPortCount() = 0; //! Pure virtual getPortName() function. virtual std::string getPortName( unsigned int portNumber = 0 ) = 0; //! Pure virtual closePort() function. virtual void closePort( void ) = 0; protected: RtMidi(); virtual ~RtMidi() {}; // A basic error reporting function for internal use in the RtMidi // subclasses. The behavior of this function can be modified to // suit specific needs. void error( RtError::Type type ); void *apiData_; bool connected_; std::string errorString_; }; /**********************************************************************/ /*! \class RtMidiIn \brief A realtime MIDI input class. This class provides a common, platform-independent API for realtime MIDI input. It allows access to a single MIDI input port. Incoming MIDI messages are either saved to a queue for retrieval using the getMessage() function or immediately passed to a user-specified callback function. Create multiple instances of this class to connect to more than one MIDI device at the same time. With the OS-X and Linux ALSA MIDI APIs, it is also possible to open a virtual input port to which other MIDI software clients can connect. by Gary P. Scavone, 2003-2004. */ /**********************************************************************/ #include #include class RtMidiIn : public RtMidi { public: //! User callback function type definition. typedef void (*RtMidiCallback)( double timeStamp, std::vector *message, void *userData); //! Default constructor. /*! An exception will be thrown if a MIDI system initialization error occurs. */ RtMidiIn(); //! If a MIDI connection is still open, it will be closed by the destructor. ~RtMidiIn(); //! Open a MIDI input connection. /*! An optional port number greater than 0 can be specified. Otherwise, the default or first port found is opened. */ void openPort( unsigned int portNumber = 0 ); //! Create a virtual input port to allow software connections (OS X and ALSA only). /*! This function creates a virtual MIDI input port to which other software applications can connect. This type of functionality is currently only supported by the Macintosh OS-X and Linux ALSA APIs (the function does nothing for the other APIs). */ void openVirtualPort(); //! Set a callback function to be invoked for incoming MIDI messages. /*! The callback function will be called whenever an incoming MIDI message is received. While not absolutely necessary, it is best to set the callback function before opening a MIDI port to avoid leaving some messages in the queue. */ void setCallback( RtMidiCallback callback, void *userData = 0 ); //! Cancel use of the current callback function (if one exists). /*! Subsequent incoming MIDI messages will be written to the queue and can be retrieved with the \e getMessage function. */ void cancelCallback(); //! Close an open MIDI connection (if one exists). void closePort( void ); //! Return the number of available MIDI input ports. unsigned int getPortCount(); //! Return a string identifier for the specified MIDI input port number. /*! An exception is thrown if an invalid port specifier is provided. */ std::string getPortName( unsigned int portNumber = 0 ); //! Set the maximum number of MIDI messages to be saved in the queue. /*! If the queue size limit is reached, incoming messages will be ignored. The default limit is 1024. */ void setQueueSizeLimit( unsigned int queueSize ); //! Specify whether certain MIDI message types should be queued or ignored during input. /*! By default, MIDI timing and active sensing messages are ignored during message input because of their relative high data rates. MIDI sysex messages are ignored by default as well. Variable values of "true" imply that the respective message type will be ignored. */ void ignoreTypes( bool midiSysex = true, bool midiTime = true, bool midiSense = true ); //! Fill the user-provided vector with the data bytes for the next available MIDI message in the input queue and return the event delta-time in seconds. /*! This function returns immediately whether a new message is available or not. A valid message is indicated by a non-zero vector size. An exception is thrown if an error occurs during message retrieval or an input connection was not previously established. */ double getMessage( std::vector *message ); // A MIDI structure used internally by the class to store incoming // messages. Each message represents one and only one MIDI message. struct MidiMessage { std::vector bytes; double timeStamp; // Default constructor. MidiMessage() :bytes(3), timeStamp(0.0) {} }; // The RtMidiInData structure is used to pass private class data to // the MIDI input handling function or thread. struct RtMidiInData { std::queue queue; unsigned int queueLimit; unsigned char ignoreFlags; bool doInput; bool firstMessage; void *apiData; bool usingCallback; void *userCallback; void *userData; // Default constructor. RtMidiInData() : queueLimit(1024), ignoreFlags(7), doInput(false), firstMessage(true), apiData(0), usingCallback(false), userCallback(0), userData(0) {} }; private: void initialize( void ); RtMidiInData inputData_; }; /**********************************************************************/ /*! \class RtMidiOut \brief A realtime MIDI output class. This class provides a common, platform-independent API for MIDI output. It allows one to probe available MIDI output ports, to connect to one such port, and to send MIDI bytes immediately over the connection. Create multiple instances of this class to connect to more than one MIDI device at the same time. by Gary P. Scavone, 2003-2004. */ /**********************************************************************/ class RtMidiOut : public RtMidi { public: //! Default constructor. /*! An exception will be thrown if a MIDI system initialization error occurs. */ RtMidiOut(); //! The destructor closes any open MIDI connections. ~RtMidiOut(); //! Open a MIDI output connection. /*! An optional port number greater than 0 can be specified. Otherwise, the default or first port found is opened. An exception is thrown if an error occurs while attempting to make the port connection. */ void openPort( unsigned int portNumber = 0 ); //! Close an open MIDI connection (if one exists). void closePort(); //! Create a virtual output port to allow software connections (OS X and ALSA only). /*! This function creates a virtual MIDI output port to which other software applications can connect. This type of functionality is currently only supported by the Macintosh OS-X and Linux ALSA APIs (the function does nothing with the other APIs). An exception is thrown if an error occurs while attempting to create the virtual port. */ void openVirtualPort(); //! Return the number of available MIDI output ports. unsigned int getPortCount(); //! Return a string identifier for the specified MIDI port type and number. /*! An exception is thrown if an invalid port specifier is provided. */ std::string getPortName( unsigned int portNumber ); //! Immediately send a single message out an open MIDI output port. /*! An exception is thrown if an error occurs during output or an output connection was not previously established. */ void sendMessage( std::vector *message ); private: void initialize( void ); }; #endif chuck-1.2.0.8.dfsg/src/ugen_filter.cpp0000644000175000017500000023051410600421721016141 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_filter.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "ugen_filter.h" #include "chuck_type.h" #include #include static t_CKUINT g_srate = 0; static t_CKFLOAT g_radians_per_sample = 0; // filter member data offset static t_CKUINT FilterBasic_offset_data = 0; static t_CKUINT biquad_offset_data = 0; //----------------------------------------------------------------------------- // name: filter_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY filter_query( Chuck_DL_Query * QUERY ) { // set srate g_srate = QUERY->srate; // set radians per sample g_radians_per_sample = TWO_PI / (t_CKFLOAT)g_srate; Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; // deprecate type_engine_register_deprecate( env, "filter", "Filter" ); type_engine_register_deprecate( env, "biquad", "BiQuad" ); type_engine_register_deprecate( env, "onepole", "OnePole" ); type_engine_register_deprecate( env, "onezero", "OneZero" ); type_engine_register_deprecate( env, "twopole", "TwoPole" ); type_engine_register_deprecate( env, "twozero", "TwoZero" ); type_engine_register_deprecate( env, "delay", "Delay" ); type_engine_register_deprecate( env, "delayl", "DelayL" ); type_engine_register_deprecate( env, "delaya", "DelayA" ); //--------------------------------------------------------------------- // init as base class: FilterBasic //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "FilterBasic", "UGen", env->global(), FilterBasic_ctor, FilterBasic_dtor, FilterBasic_tick, FilterBasic_pmsg ) ) return FALSE; // member variable FilterBasic_offset_data = type_engine_import_mvar( env, "int", "@FilterBasic_data", FALSE ); if( FilterBasic_offset_data == CK_INVALID_OFFSET ) goto error; // freq func = make_new_mfun( "float", "freq", FilterBasic_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", FilterBasic_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // Q func = make_new_mfun( "float", "Q", FilterBasic_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", FilterBasic_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", FilterBasic_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); /* //--------------------------------------------------------------------- // init class: LPF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "LPF", "FilterBasic", env->global(), LPF_ctor, LPF_tick, LPF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", LPF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", LPF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init class: HPF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "HPF", "FilterBasic", env->global(), HPF_ctor, HPF_tick, HPF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", HPF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", HPF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); */ //--------------------------------------------------------------------- // init class: BPF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "BPF", "FilterBasic", env->global(), BPF_ctor, NULL, BPF_tick, BPF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", BPF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", BPF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // Q func = make_new_mfun( "float", "Q", BPF_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", BPF_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", BPF_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init class: BRF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "BRF", "FilterBasic", env->global(), BRF_ctor, NULL, BRF_tick, BRF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", BRF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", BRF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // Q func = make_new_mfun( "float", "Q", BRF_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", BRF_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", BRF_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init class: RLPF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "LPF", "FilterBasic", env->global(), RLPF_ctor, NULL, RLPF_tick, RLPF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", RLPF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", RLPF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // Q func = make_new_mfun( "float", "Q", RLPF_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", RLPF_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", RLPF_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init class: RHPF //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "HPF", "FilterBasic", env->global(), RHPF_ctor, NULL, RHPF_tick, RHPF_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", RHPF_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", RHPF_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // Q func = make_new_mfun( "float", "Q", RHPF_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", RHPF_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", RHPF_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init class: ResonZ //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "ResonZ", "FilterBasic", env->global(), ResonZ_ctor, NULL, ResonZ_tick, ResonZ_pmsg ) ) return FALSE; // freq func = make_new_mfun( "float", "freq", ResonZ_ctrl_freq ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", ResonZ_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // reson func = make_new_mfun( "float", "Q", ResonZ_ctrl_Q ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "Q", ResonZ_cget_Q ); if( !type_engine_import_mfun( env, func ) ) goto error; // set func = make_new_mfun( "void", "set", ResonZ_ctrl_set ); func->add_arg( "float", "freq" ); func->add_arg( "float", "Q" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // init as base class: BiQuad //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "BiQuad", "UGen", env->global(), biquad_ctor, biquad_dtor, biquad_tick, NULL ) ) return FALSE; // member variable biquad_offset_data = type_engine_import_mvar ( env, "int", "@biquad_data", FALSE ); if ( biquad_offset_data == CK_INVALID_OFFSET ) goto error; // pfreq func = make_new_mfun ( "float", "pfreq", biquad_ctrl_pfreq ); func->add_arg ( "float", "freq" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "pfreq", biquad_cget_pfreq ); if( !type_engine_import_mfun( env, func ) ) goto error; // prad func = make_new_mfun ( "float", "prad", biquad_ctrl_prad ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "prad", biquad_cget_prad ); if( !type_engine_import_mfun( env, func ) ) goto error; // zfreq func = make_new_mfun ( "float", "zfreq", biquad_ctrl_zfreq ); func->add_arg ( "float", "freq" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "zfreq", biquad_cget_zfreq ); if( !type_engine_import_mfun( env, func ) ) goto error; // zrad func = make_new_mfun ( "float", "zrad", biquad_ctrl_zrad ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "zrad", biquad_cget_zrad ); if( !type_engine_import_mfun( env, func ) ) goto error; // norm func = make_new_mfun ( "int", "norm", biquad_ctrl_norm ); func->add_arg ( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "int", "norm", biquad_cget_norm ); if( !type_engine_import_mfun( env, func ) ) goto error; // pregain func = make_new_mfun ( "float", "pregain", biquad_ctrl_pregain ); func->add_arg ( "float", "level" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "pregain", biquad_cget_pregain ); if( !type_engine_import_mfun( env, func ) ) goto error; // eqzs func = make_new_mfun ( "int", "eqzs", biquad_ctrl_eqzs ); func->add_arg ( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // b0 func = make_new_mfun ( "float", "b0", biquad_ctrl_b0 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "b0", biquad_cget_b0 ); if( !type_engine_import_mfun( env, func ) ) goto error; // b1 func = make_new_mfun ( "float", "b1", biquad_ctrl_b1 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "b1", biquad_cget_b1 ); if( !type_engine_import_mfun( env, func ) ) goto error; // b2 func = make_new_mfun ( "float", "b2", biquad_ctrl_b2 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "b2", biquad_cget_b2 ); if( !type_engine_import_mfun( env, func ) ) goto error; // a0 func = make_new_mfun ( "float", "a0", biquad_ctrl_a0 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "a0", biquad_cget_a0 ); if( !type_engine_import_mfun( env, func ) ) goto error; // a1 func = make_new_mfun ( "float", "a1", biquad_ctrl_a1 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "a1", biquad_cget_a1 ); if( !type_engine_import_mfun( env, func ) ) goto error; // a2 func = make_new_mfun ( "float", "a2", biquad_ctrl_a2 ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "a2", biquad_cget_a2 ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); /* //---------------------------------- // begin onepole ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "OnePole", "biquad", env->global(), NULL, onepole_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "pole", onepole_ctrl_pole ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin onezero ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "onezero", "biquad", env->global(), NULL, onezero_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "zero", onezero_ctrl_zero ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin twopole ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "twopole", "biquad", env->global(), NULL, twopole_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "freq", twopole_ctrl_freq ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "rad", twopole_ctrl_rad ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "int", "norm", twopole_ctrl_norm ); func->add_arg ( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin twozero ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "twozero", "biquad", env->global(), NULL, twozero_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "freq", twozero_ctrl_freq ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "rad", twozero_ctrl_rad ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin delay ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "delay", "UGen", env->global(), delay_ctor, delay_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "delay", delay_ctrl_delay ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "max", delay_ctrl_max ); func->add_arg ( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // QUERY->ugen_ctrl( QUERY, delay_ctrl_energy, NULL,"int", "energy" ); // QUERY->ugen_ctrl( QUERY, delay_ctrl_tap, NULL, "int", "tap" ); // QUERY->ugen_ctrl( QUERY, delay_ctrl_ftap, NULL, "float", "ftap" ); // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin delayA ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "delayA", "UGen", env->global(), delayA_ctor, delayA_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "delay", delayA_ctrl_delay ); func->add_arg ( "float", "length" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "max", delayA_ctrl_max ); func->add_arg ( "float", "max" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //---------------------------------- // begin one ugen //---------------------------------- if ( !type_engine_import_ugen_begin( env, "delayL", "UGen", env->global(), delayL_ctor, delayL_tick, NULL ) ) return FALSE; // ctrl func func = make_new_mfun ( "float", "delay", delayL_ctrl_delay ); func->add_arg ( "float", "length" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun ( "float", "max", delayL_ctrl_max ); func->add_arg ( "float", "max" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); */ return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: Filter_data // desc: ... //----------------------------------------------------------------------------- struct Filter_data { t_CKUINT nB; t_CKUINT nA; SAMPLE * b; SAMPLE * a; SAMPLE * input; SAMPLE * output; Filter_data() { a = b = NULL; alloc( 1, 1 ); a[0] = b[0] = 1.0f; } void alloc( t_CKUINT _b, t_CKUINT _a ) { nB = _b; nA = _a; if( b ) delete b; if( a ) delete a; if( input ) delete input; if( output ) delete output; b = new SAMPLE[nB]; a = new SAMPLE[nA]; input = new SAMPLE[nB]; output = new SAMPLE[nA]; } inline SAMPLE tick( SAMPLE in ) { t_CKUINT i; output[0] = 0.0; input[0] = in; for( i = nB-1; i > 0; i-- ) { output[0] += b[i] * input[i]; input[i] = input[i-1]; } output[0] += b[0] * input[0]; for ( i = nA-1; i>0; i--) { output[0] += -a[i] * output[i]; output[i] = output[i-1]; } return output[0]; } }; //----------------------------------------------------------------------------- // name: FilterBasic_data // desc: ... //----------------------------------------------------------------------------- struct FilterBasic_data { // much of this implementation is adapted or copied outright from SC3 SAMPLE m_y1; SAMPLE m_y2; SAMPLE m_a0; SAMPLE m_b1; SAMPLE m_b2; t_CKFLOAT m_freq; t_CKFLOAT m_Q; t_CKFLOAT m_db; // tick_lpf inline SAMPLE tick_lpf( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's LPF y0 = in + m_b1 * m_y1 + m_b2 * m_y2; result = m_a0 * (y0 + 2 * m_y1 + m_y2); m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // tick_hpf inline SAMPLE tick_hpf( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's HPF y0 = in + m_b1 * m_y1 + m_b2 * m_y2; result = m_a0 * (y0 - 2 * m_y1 + m_y2); m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // set_bpf inline void set_bpf( t_CKFLOAT freq, t_CKFLOAT Q ) { t_CKFLOAT pfreq = freq * g_radians_per_sample; t_CKFLOAT pbw = 1.0 / Q * pfreq * .5; t_CKFLOAT C = 1.0 / ::tan(pbw); t_CKFLOAT D = 2.0 * ::cos(pfreq); t_CKFLOAT next_a0 = 1.0 / (1.0 + C); t_CKFLOAT next_b1 = C * D * next_a0 ; t_CKFLOAT next_b2 = (1.0 - C) * next_a0; m_freq = freq; m_Q = Q; m_a0 = (SAMPLE)next_a0; m_b1 = (SAMPLE)next_b1; m_b2 = (SAMPLE)next_b2; } // tick_bpf inline SAMPLE tick_bpf( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's LPF y0 = in + m_b1 * m_y1 + m_b2 * m_y2; result = m_a0 * (y0 - m_y2); m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // set_brf inline void set_brf( t_CKFLOAT freq, t_CKFLOAT Q ) { t_CKFLOAT pfreq = freq * g_radians_per_sample; t_CKFLOAT pbw = 1.0 / Q * pfreq * .5; t_CKFLOAT C = ::tan(pbw); t_CKFLOAT D = 2.0 * ::cos(pfreq); t_CKFLOAT next_a0 = 1.0 / (1.0 + C); t_CKFLOAT next_b1 = -D * next_a0 ; t_CKFLOAT next_b2 = (1.f - C) * next_a0; m_freq = freq; m_Q = Q; m_a0 = (SAMPLE)next_a0; m_b1 = (SAMPLE)next_b1; m_b2 = (SAMPLE)next_b2; } // tick_brf inline SAMPLE tick_brf( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's HPF // b1 is actually a1 y0 = in - m_b1 * m_y1 - m_b2 * m_y2; result = m_a0 * (y0 + m_y2) + m_b1 * m_y1; m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // set_rlpf inline void set_rlpf( t_CKFLOAT freq, t_CKFLOAT Q ) { t_CKFLOAT qres = ck_max( .001, 1.0/Q ); t_CKFLOAT pfreq = freq * g_radians_per_sample; t_CKFLOAT D = ::tan(pfreq * qres * 0.5); t_CKFLOAT C = (1.0 - D) / (1.0 + D); t_CKFLOAT cosf = ::cos(pfreq); t_CKFLOAT next_b1 = (1.0 + C) * cosf; t_CKFLOAT next_b2 = -C; t_CKFLOAT next_a0 = (1.0 + C - next_b1) * 0.25; m_freq = freq; m_Q = 1.0 / qres; m_a0 = (SAMPLE)next_a0; m_b1 = (SAMPLE)next_b1; m_b2 = (SAMPLE)next_b2; } // tick_rlpf inline SAMPLE tick_rlpf( SAMPLE in ) { SAMPLE y0, result; // go: adapated from SC3's RLPF y0 = m_a0 * in + m_b1 * m_y1 + m_b2 * m_y2; result = y0 + 2 * m_y1 + m_y2; m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // set_rhpf inline void set_rhpf( t_CKFLOAT freq, t_CKFLOAT Q ) { t_CKFLOAT qres = ck_max( .001, 1.0/Q ); t_CKFLOAT pfreq = freq * g_radians_per_sample; t_CKFLOAT D = ::tan(pfreq * qres * 0.5); t_CKFLOAT C = (1.0 - D) / (1.0 + D); t_CKFLOAT cosf = ::cos(pfreq); t_CKFLOAT next_b1 = (1.0 + C) * cosf; t_CKFLOAT next_b2 = -C; t_CKFLOAT next_a0 = (1.0 + C + next_b1) * 0.25; m_freq = freq; m_Q = 1.0 / qres; m_a0 = (SAMPLE)next_a0; m_b1 = (SAMPLE)next_b1; m_b2 = (SAMPLE)next_b2; } // tick_rhpf inline SAMPLE tick_rhpf( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's RHPF y0 = m_a0 * in + m_b1 * m_y1 + m_b2 * m_y2; result = y0 - 2 * m_y1 + m_y2; m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } // set_resonz inline void set_resonz( t_CKFLOAT freq, t_CKFLOAT Q ) { t_CKFLOAT pfreq = freq * g_radians_per_sample; t_CKFLOAT B = pfreq / Q; t_CKFLOAT R = 1.0 - B * 0.5; t_CKFLOAT R2 = 2.0 * R; t_CKFLOAT R22 = R * R; t_CKFLOAT cost = (R2 * ::cos(pfreq)) / (1.0 + R22); t_CKFLOAT next_b1 = R2 * cost; t_CKFLOAT next_b2 = -R22; t_CKFLOAT next_a0 = (1.0 - R22) * 0.5; m_freq = freq; m_Q = Q; m_a0 = (SAMPLE)next_a0; m_b1 = (SAMPLE)next_b1; m_b2 = (SAMPLE)next_b2; } // tick_resonz inline SAMPLE tick_resonz( SAMPLE in ) { SAMPLE y0, result; // go: adapted from SC3's ResonZ y0 = in + m_b1 * m_y1 + m_b2 * m_y2; result = m_a0 * (y0 - m_y2); m_y2 = m_y1; m_y1 = y0; // be normal CK_DDN(m_y1); CK_DDN(m_y2); return result; } }; //----------------------------------------------------------------------------- // name: FilterBasic_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( FilterBasic_ctor ) { // set to zero OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = 0; } //----------------------------------------------------------------------------- // name: FilterBasic_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( FilterBasic_dtor ) { // get data FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // delete SAFE_DELETE(d); // set OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = 0; } //----------------------------------------------------------------------------- // name: FilterBasic_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( FilterBasic_tick ) { fprintf( stderr, "FilterBasic.tick() --> FitlerBasic is virtual!\n" ); return TRUE; } //----------------------------------------------------------------------------- // name: FilterBasic_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FilterBasic_ctrl_freq ) { } //----------------------------------------------------------------------------- // name: FilterBasic_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( FilterBasic_cget_freq ) { } //----------------------------------------------------------------------------- // name: FilterBasic_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( FilterBasic_ctrl_Q ) { } //----------------------------------------------------------------------------- // name: FilterBasic_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( FilterBasic_cget_Q ) { } //----------------------------------------------------------------------------- // name: FilterBasic_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( FilterBasic_ctrl_set ) { } //----------------------------------------------------------------------------- // name: FilterBasic_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( FilterBasic_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: LPF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( LPF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: LPF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( LPF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_lpf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: LPF_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LPF_ctrl_freq ) { // implementation: adapted from SC3's LPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT pfreq = freq * g_radians_per_sample * 0.5; t_CKFLOAT C = 1.0 / ::tan(pfreq); t_CKFLOAT C2 = C * C; t_CKFLOAT sqrt2C = C * SQRT2; t_CKFLOAT next_a0 = 1.0 / (1.0 + sqrt2C + C2); t_CKFLOAT next_b1 = -2.0 * (1.0 - C2) * next_a0 ; t_CKFLOAT next_b2 = -(1.f - sqrt2C + C2) * next_a0; d->m_freq = freq; d->m_a0 = (SAMPLE)next_a0; d->m_b1 = (SAMPLE)next_b1; d->m_b2 = (SAMPLE)next_b2; RETURN->v_float = freq; } //----------------------------------------------------------------------------- // name: LPF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LPF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: LPF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( LPF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: HPF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( HPF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: HPF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( HPF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_hpf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: HPF_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( HPF_ctrl_freq ) { // implementation: adapted from SC3's HPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT pfreq = freq * g_radians_per_sample * 0.5; t_CKFLOAT C = ::tan(pfreq); t_CKFLOAT C2 = C * C; t_CKFLOAT sqrt2C = C * SQRT2; t_CKFLOAT next_a0 = 1.0 / (1.0 + sqrt2C + C2); t_CKFLOAT next_b1 = 2.0 * (1.0 - C2) * next_a0 ; t_CKFLOAT next_b2 = -(1.0 - sqrt2C + C2) * next_a0; d->m_freq = freq; d->m_a0 = (SAMPLE)next_a0; d->m_b1 = (SAMPLE)next_b1; d->m_b2 = (SAMPLE)next_b2; RETURN->v_float = freq; } //----------------------------------------------------------------------------- // name: HPF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( HPF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: HPF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( HPF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: BPF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BPF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: BPF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BPF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_bpf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: BPF_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BPF_ctrl_freq ) { // implementation: adapted from SC3's BPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); // set d->set_bpf( freq, d->m_Q ); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: BPF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( BPF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: BPF_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BPF_ctrl_Q ) { // implementation: adapted from SC3's BPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_bpf( d->m_freq, Q ); RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: BPF_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( BPF_cget_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: BPF_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BPF_ctrl_set ) { // implementation: adapted from SC3's BPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_bpf( freq, Q ); } //----------------------------------------------------------------------------- // name: BPF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BPF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: BRF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BRF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: BRF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BRF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_brf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: BRF_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BRF_ctrl_freq ) { // implementation: adapted from SC3's BRF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); // set d->set_brf( freq, d->m_Q ); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: BRF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( BRF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: BRF_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BRF_ctrl_Q ) { // implementation: adapted from SC3's BRF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_brf( d->m_freq, Q ); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: BRF_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( BRF_cget_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: BRF_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( BRF_ctrl_set ) { // implementation: adapted from SC3's BRF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_brf( freq, Q ); } //----------------------------------------------------------------------------- // name: BRF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BRF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: RLPF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( RLPF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); // default f->m_Q = 1.0; OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: RLPF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( RLPF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_rlpf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: RLPF_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RLPF_ctrl_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); // set d->set_rlpf( freq, d->m_Q ); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: RLPF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( RLPF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: RLPF_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RLPF_ctrl_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_rlpf( d->m_freq, Q ); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: RLPF_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( RLPF_cget_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: RLPF_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RLPF_ctrl_set ) { // implementation: adapted from SC3's RLPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_rlpf( freq, Q ); RETURN->v_float = freq; } //----------------------------------------------------------------------------- // name: RLPF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( RLPF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: ResonZ_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( ResonZ_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); // default f->m_Q = 1.0; OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: ResonZ_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( ResonZ_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_resonz( in ); return TRUE; } //----------------------------------------------------------------------------- // name: ResonZ_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( ResonZ_ctrl_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); // set d->set_resonz( freq, d->m_Q ); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: ResonZ_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( ResonZ_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: ResonZ_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( ResonZ_ctrl_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_resonz( d->m_freq, Q ); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: ResonZ_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( ResonZ_cget_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: ResonZ_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( ResonZ_ctrl_set ) { // implementation: adapted from SC3's RLPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_resonz( freq, Q ); RETURN->v_float = freq; } //----------------------------------------------------------------------------- // name: ResonZ_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( ResonZ_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: RHPF_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( RHPF_ctor ) { FilterBasic_data * f = new FilterBasic_data; memset( f, 0, sizeof(FilterBasic_data) ); // default f->m_Q = 1.0; OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data) = (t_CKUINT)f; } //----------------------------------------------------------------------------- // name: RHPF_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( RHPF_tick ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); *out = d->tick_rhpf( in ); return TRUE; } //----------------------------------------------------------------------------- // name: RHPF_ctrl_freq() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RHPF_ctrl_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); // set d->set_rhpf( freq, d->m_Q ); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: RHPF_cget_freq() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( RHPF_cget_freq ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_freq; } //----------------------------------------------------------------------------- // name: RHPF_ctrl_Q() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RHPF_ctrl_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_rhpf( d->m_freq, Q ); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: RHPF_cget_Q() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( RHPF_cget_Q ) { FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); // return RETURN->v_float = d->m_Q; } //----------------------------------------------------------------------------- // name: RHPF_ctrl_set() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( RHPF_ctrl_set ) { // implementation: adapted from SC3's RLPF FilterBasic_data * d = (FilterBasic_data *)OBJ_MEMBER_UINT(SELF, FilterBasic_offset_data); t_CKFLOAT freq = GET_NEXT_FLOAT(ARGS); t_CKFLOAT Q = GET_NEXT_FLOAT(ARGS); // set d->set_rlpf( freq, Q ); } //----------------------------------------------------------------------------- // name: RHPF_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( RHPF_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: biquad // desc: biquad filter //----------------------------------------------------------------------------- struct biquad_data { SAMPLE m_a0, m_a1, m_a2; SAMPLE m_b0, m_b1, m_b2; SAMPLE m_input0, m_input1, m_input2; SAMPLE m_output0, m_output1, m_output2; t_CKFLOAT pfreq, zfreq; t_CKFLOAT prad, zrad; t_CKBOOL norm; t_CKUINT srate; biquad_data() { m_a0 = m_b0 = 1.0f; m_a1 = m_a2 = 0.0f; m_b1 = 0.0f; m_b2 = 0.0f; m_input0 = m_input1 = m_input2 = 0.0f; m_output0 = m_output1 = m_output2 = 0.0f; pfreq = zfreq = 0.0f; prad = zrad = 0.0f; norm = FALSE; srate = g_srate; } }; //----------------------------------------------------------------------------- // name: biquad_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( biquad_ctor ) { biquad_data* d = new biquad_data; OBJ_MEMBER_UINT( SELF, biquad_offset_data ) = ( t_CKUINT ) d; } //----------------------------------------------------------------------------- // name: biquad_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( biquad_dtor ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); SAFE_DELETE( d ); OBJ_MEMBER_UINT(SELF, biquad_offset_data) = 0; } //----------------------------------------------------------------------------- // name: biquad_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( biquad_tick ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_input0 = d->m_a0 * in; d->m_output0 = d->m_b0 * d->m_input0 + d->m_b1 * d->m_input1 + d->m_b2 * d->m_input2; d->m_output0 -= d->m_a2 * d->m_output2 + d->m_a1 * d->m_output1; d->m_input2 = d->m_input1; d->m_input1 = d->m_input0; d->m_output2 = d->m_output1; d->m_output1 = d->m_output0; // be normal CK_DDN(d->m_output1); CK_DDN(d->m_output2); *out = (SAMPLE)d->m_output0; return TRUE; } void biquad_set_reson( biquad_data * d ) { d->m_a2 = (SAMPLE)(d->prad * d->prad); d->m_a1 = (SAMPLE)(-2.0 * d->prad * cos(2.0 * ONE_PI * d->pfreq / (double)d->srate)); if ( d->norm ) { // Use zeros at +- 1 and normalize the filter peak gain. d->m_b0= 0.5f - 0.5f * d->m_a2; d->m_b1 = -1.0f; d->m_b2 = -d->m_b0; } } //----------------------------------------------------------------------------- // name: biquad_ctrl_pfreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_pfreq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->pfreq = GET_CK_FLOAT(ARGS); biquad_set_reson( d ); RETURN->v_float = d->pfreq; } //----------------------------------------------------------------------------- // name: biquad_cget_pfreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_pfreq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->pfreq; } //----------------------------------------------------------------------------- // name: biquad_ctrl_prad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_prad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->prad = GET_CK_FLOAT(ARGS); biquad_set_reson( d ); RETURN->v_float = d->prad; } //----------------------------------------------------------------------------- // name: biquad_cget_prad() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_prad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->prad; } void biquad_set_notch( biquad_data * d ) { d->m_b2 = (SAMPLE)(d->zrad * d->zrad); d->m_b1 = (SAMPLE)(-2.0 * d->zrad * cos(2.0 * ONE_PI * d->zfreq / (double)d->srate)); } //----------------------------------------------------------------------------- // name: biquad_ctrl_zfreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_zfreq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->zfreq = GET_CK_FLOAT(ARGS); biquad_set_notch( d ); RETURN->v_float = d->zfreq; } //----------------------------------------------------------------------------- // name: biquad_cget_zfreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_zfreq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->zfreq; } //----------------------------------------------------------------------------- // name: biquad_ctrl_zrad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_zrad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->zrad = GET_CK_FLOAT(ARGS); biquad_set_notch( d ); RETURN->v_float = d->zrad; } //----------------------------------------------------------------------------- // name: biquad_cget_zrad() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_zrad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->zrad; } //----------------------------------------------------------------------------- // name: biquad_ctrl_norm() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_norm ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->norm = *(t_CKBOOL *)ARGS; biquad_set_reson( d ); RETURN->v_int = d->norm; } //----------------------------------------------------------------------------- // name: biquad_cget_norm() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_norm ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_int = d->norm; } //----------------------------------------------------------------------------- // name: biquad_ctrl_pregain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_pregain ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_a0 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_a0; } //----------------------------------------------------------------------------- // name: biquad_cget_pregain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_pregain ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_a0; } //----------------------------------------------------------------------------- // name: biquad_ctrl_eqzs() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_eqzs ) { if( *(t_CKUINT *)ARGS ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_b0 = 1.0f; d->m_b1 = 0.0f; d->m_b2 = -1.0f; } RETURN->v_int = *(t_CKUINT *)ARGS; } //----------------------------------------------------------------------------- // name: biquad_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_b0 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_b0 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_b0; } //----------------------------------------------------------------------------- // name: biquad_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_b0 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_b0; } //----------------------------------------------------------------------------- // name: biquad_ctrl_b1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_b1 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_b1 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_b1; } //----------------------------------------------------------------------------- // name: biquad_cget_b1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_b1 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_b1; } //----------------------------------------------------------------------------- // name: biquad_ctrl_b2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_b2 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_b2 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_b2; } //----------------------------------------------------------------------------- // name: biquad_cget_b2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_b2 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_b2; } //----------------------------------------------------------------------------- // name: biquad_ctrl_a0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_a0 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_a0 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_a0; } //----------------------------------------------------------------------------- // name: biquad_cget_a0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_a0 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_a0; } //----------------------------------------------------------------------------- // name: biquad_ctrl_a1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_a1 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_a1 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_a1; } //----------------------------------------------------------------------------- // name: biquad_cget_a1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_a1 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_a1; } //----------------------------------------------------------------------------- // name: biquad_ctrl_a2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_ctrl_a2 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_a2 = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = d->m_a2; } //----------------------------------------------------------------------------- // name: biquad_cget_a2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( biquad_cget_a2 ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); RETURN->v_float = d->m_a2; } //----------------------------------------------------------------------------- // name: onepole // desc: onepole filter //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: onepole_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( onepole_tick ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_input0 = in; d->m_output0 = d->m_b0 * d->m_input0 - d->m_a1 * d->m_output1; d->m_output1 = d->m_output0; *out = d->m_output0; return TRUE; } //----------------------------------------------------------------------------- // name: onepole_ctrl_pole() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( onepole_ctrl_pole ) { float f = (float)GET_CK_FLOAT(ARGS); biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); if( f > 0.0f ) d->m_b0 = 1.0f - f; else d->m_b0 = 1.0f + f; d->m_a0 = -f; } //----------------------------------------------------------------------------- // name: onezero // desc: onezero filter //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: onezero_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( onezero_tick ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_input0 = in; d->m_output0 = d->m_b1 * d->m_input1 + d->m_b0 * d->m_input0; d->m_input1 = d->m_input0; *out = d->m_output0; return TRUE; } //----------------------------------------------------------------------------- // name: onezero_ctrl_zero() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( onezero_ctrl_zero ) { float f = (float)GET_CK_FLOAT(ARGS); biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); if( f > 0.0f ) d->m_b0 = 1.0f / ( 1.0f + f ); else d->m_b0 = 1.0f / ( 1.0f - f ); d->m_b1 = -f * d->m_b0; } //----------------------------------------------------------------------------- // name: twopole // desc: twopole filter //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: twopole_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( twopole_tick ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_input0 = in; d->m_output0 = d->m_b0 * d->m_input0 - d->m_a2 * d->m_output2 - d->m_a1 * d->m_output1; d->m_output2 = d->m_output1; d->m_output1 = d->m_output0; *out = d->m_output0; return TRUE; } //----------------------------------------------------------------------------- // name: twopole_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( twopole_ctrl_freq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->pfreq = (float)GET_CK_FLOAT(ARGS); biquad_set_reson( d ); if( d->norm ) { // Normalize the filter gain ... not terribly efficient. double real = 1.0 - d->prad + (d->m_a2 - d->prad) * cos( 2.0 * ONE_PI * d->pfreq / d->srate ); double imag = (d->m_a2 - d->prad) * sin( 2.0 * ONE_PI * d->pfreq / d->srate ); d->m_b0 = sqrt( real*real + imag*imag ); } } //----------------------------------------------------------------------------- // name: twopole_ctrl_rad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( twopole_ctrl_rad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->prad = (float)GET_CK_FLOAT(ARGS); biquad_set_reson( d ); if( d->norm ) { // Normalize the filter gain ... not terrbly efficient double real = 1.0 - d->prad + (d->m_a2 - d->prad) * cos( 2.0 * ONE_PI * d->pfreq / d->srate ); double imag = (d->m_a2 - d->prad) * sin( 2.0 * ONE_PI * d->pfreq / d->srate ); d->m_b0 = sqrt( real*real + imag*imag ); } } //----------------------------------------------------------------------------- // name: twopole_ctrl_norm() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( twopole_ctrl_norm ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->norm = *(t_CKBOOL *)ARGS; if( d->norm ) { // Normalize the filter gain ... not terribly efficient double real = 1.0 - d->prad + (d->m_a2 - d->prad) * cos( 2.0 * ONE_PI * d->pfreq / d->srate ); double imag = (d->m_a2 - d->prad) * sin( 2.0 * ONE_PI * d->pfreq / d->srate ); d->m_b0 = sqrt( real*real + imag*imag ); } } //----------------------------------------------------------------------------- // name: twozero // desc: twozero filter //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: twozero_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( twozero_tick ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->m_input0 = in; d->m_output0 = d->m_b0 * d->m_input0 + d->m_b1 * d->m_input1 + d->m_b2 * d->m_input2; d->m_input2 = d->m_input1; d->m_input1 = d->m_input0; *out = d->m_output0; return TRUE; } //----------------------------------------------------------------------------- // name: twozero_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( twozero_ctrl_freq ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->zfreq = (float)GET_CK_FLOAT(ARGS); biquad_set_notch( d ); // normalize the filter gain if( d->m_b1 > 0.0f ) d->m_b0 = 1.0f / (1.0f+d->m_b1+d->m_b2); else d->m_b0 = 1.0f / (1.0f-d->m_b1+d->m_b2); d->m_b1 *= d->m_b0; d->m_b2 *= d->m_b0; } //----------------------------------------------------------------------------- // name: twozero_ctrl_rad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( twozero_ctrl_rad ) { biquad_data * d = (biquad_data *)OBJ_MEMBER_UINT(SELF, biquad_offset_data ); d->zrad = (float)GET_CK_FLOAT(ARGS); biquad_set_notch( d ); // normalize the filter gain if( d->m_b1 > 0.0f ) d->m_b0 = 1.0f / (1.0f+d->m_b1+d->m_b2); else d->m_b0 = 1.0f / (1.0f-d->m_b1+d->m_b2); d->m_b1 *= d->m_b0; d->m_b2 *= d->m_b0; } //----------------------------------------------------------------------------- // name: gQ // desc: gQ filter - a la Dan Trueman //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: gQ_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( gQ_tick ) { return TRUE; } //----------------------------------------------------------------------------- // name: gQ_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( gQ_ctrl_freq ) { } //----------------------------------------------------------------------------- // name: gQ_ctrl_rad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( gQ_ctrl_rad ) { } /* //----------------------------------------------------------------------------- // name: allpass // desc: allpass filter //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: allpass_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( allpass_tick ) { return TRUE; } //----------------------------------------------------------------------------- // name: allpass_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( allpass_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: delay // desc: ... //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: delay_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( delay_ctor ) { } //----------------------------------------------------------------------------- // name: delay_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( delay_tick ) { return TRUE; } //----------------------------------------------------------------------------- // name: delay_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delay_ctrl_delay ) { } //----------------------------------------------------------------------------- // name: delay_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delay_ctrl_max ) { } //----------------------------------------------------------------------------- // name: delay_ctrl_tap() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delay_ctrl_tap ) { } //----------------------------------------------------------------------------- // name: delay_ctrl_energy() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delay_ctrl_energy ) { } //----------------------------------------------------------------------------- // name: delayA // desc: delay - allpass interpolation //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: delayA_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( delayA_ctor ) { } //----------------------------------------------------------------------------- // name: delayA_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( delayA_tick ) { return TRUE; } //----------------------------------------------------------------------------- // name: delayA_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delayA_ctrl_delay ) { } //----------------------------------------------------------------------------- // name: delayA_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delayA_ctrl_max ) { } //----------------------------------------------------------------------------- // name: delayL // desc: delay - linear interpolation //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: delayL_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( delayL_ctor ) { } //----------------------------------------------------------------------------- // name: delayL_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( delayL_tick ) { return TRUE; } //----------------------------------------------------------------------------- // name: delayL_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delayL_ctrl_delay ) { } //----------------------------------------------------------------------------- // name: delayL_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( delayL_ctrl_max ) { } */ chuck-1.2.0.8.dfsg/src/ugen_filter.h0000644000175000017500000001405510600421721015606 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_filter.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip L. Davidson (philipd@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __UGEN_FILTER_H__ #define __UGEN_FILTER_H__ #include "chuck_dl.h" // query DLL_QUERY filter_query( Chuck_DL_Query * query ); // FilterBasic CK_DLL_CTOR( FilterBasic_ctor ); CK_DLL_DTOR( FilterBasic_dtor ); CK_DLL_TICK( FilterBasic_tick ); CK_DLL_PMSG( FilterBasic_pmsg ); CK_DLL_CTRL( FilterBasic_ctrl_freq ); CK_DLL_CGET( FilterBasic_cget_freq ); CK_DLL_CTRL( FilterBasic_ctrl_Q ); CK_DLL_CGET( FilterBasic_cget_Q ); CK_DLL_CTRL( FilterBasic_ctrl_set ); // LPF CK_DLL_CTOR( LPF_ctor ); CK_DLL_DTOR( LPF_dtor ); CK_DLL_TICK( LPF_tick ); CK_DLL_PMSG( LPF_pmsg ); CK_DLL_CTRL( LPF_ctrl_freq ); CK_DLL_CGET( LPF_cget_freq ); // HPF CK_DLL_CTOR( HPF_ctor ); CK_DLL_DTOR( HPF_dtor ); CK_DLL_TICK( HPF_tick ); CK_DLL_PMSG( HPF_pmsg ); CK_DLL_CTRL( HPF_ctrl_freq ); CK_DLL_CGET( HPF_cget_freq ); // BPF CK_DLL_CTOR( BPF_ctor ); CK_DLL_DTOR( BPF_dtor ); CK_DLL_TICK( BPF_tick ); CK_DLL_PMSG( BPF_pmsg ); CK_DLL_CTRL( BPF_ctrl_freq ); CK_DLL_CGET( BPF_cget_freq ); CK_DLL_CTRL( BPF_ctrl_Q ); CK_DLL_CGET( BPF_cget_Q ); CK_DLL_CTRL( BPF_ctrl_set ); // BRF CK_DLL_CTOR( BRF_ctor ); CK_DLL_DTOR( BRF_dtor ); CK_DLL_TICK( BRF_tick ); CK_DLL_PMSG( BRF_pmsg ); CK_DLL_CTRL( BRF_ctrl_freq ); CK_DLL_CGET( BRF_cget_freq ); CK_DLL_CTRL( BRF_ctrl_Q ); CK_DLL_CGET( BRF_cget_Q ); CK_DLL_CTRL( BRF_ctrl_set ); // RLPF CK_DLL_CTOR( RLPF_ctor ); CK_DLL_DTOR( RLPF_dtor ); CK_DLL_TICK( RLPF_tick ); CK_DLL_PMSG( RLPF_pmsg ); CK_DLL_CTRL( RLPF_ctrl_freq ); CK_DLL_CGET( RLPF_cget_freq ); CK_DLL_CTRL( RLPF_ctrl_Q ); CK_DLL_CGET( RLPF_cget_Q ); CK_DLL_CTRL( RLPF_ctrl_set ); // RHPF CK_DLL_CTOR( RHPF_ctor ); CK_DLL_DTOR( RHPF_dtor ); CK_DLL_TICK( RHPF_tick ); CK_DLL_PMSG( RHPF_pmsg ); CK_DLL_CTRL( RHPF_ctrl_freq ); CK_DLL_CGET( RHPF_cget_freq ); CK_DLL_CTRL( RHPF_ctrl_Q ); CK_DLL_CGET( RHPF_cget_Q ); CK_DLL_CTRL( RHPF_ctrl_set ); // ResonZ CK_DLL_CTOR( ResonZ_ctor ); CK_DLL_DTOR( ResonZ_dtor ); CK_DLL_TICK( ResonZ_tick ); CK_DLL_PMSG( ResonZ_pmsg ); CK_DLL_CTRL( ResonZ_ctrl_freq ); CK_DLL_CGET( ResonZ_cget_freq ); CK_DLL_CTRL( ResonZ_ctrl_Q ); CK_DLL_CGET( ResonZ_cget_Q ); CK_DLL_CTRL( ResonZ_ctrl_set ); // filter CK_DLL_CTOR( filter_ctor ); CK_DLL_DTOR( filter_dtor ); CK_DLL_TICK( filter_tick ); CK_DLL_CTRL( filter_ctrl_coefs ); CK_DLL_CGET( filter_cget_coefs ); CK_DLL_PMSG( filter_pmsg ); // biquad CK_DLL_CTOR( biquad_ctor ); CK_DLL_DTOR( biquad_dtor ); CK_DLL_TICK( biquad_tick ); CK_DLL_CTRL( biquad_ctrl_pfreq ); CK_DLL_CGET( biquad_cget_pfreq ); CK_DLL_CTRL( biquad_ctrl_prad ); CK_DLL_CGET( biquad_cget_prad ); CK_DLL_CTRL( biquad_ctrl_zfreq ); CK_DLL_CGET( biquad_cget_zfreq ); CK_DLL_CTRL( biquad_ctrl_zrad ); CK_DLL_CGET( biquad_cget_zrad ); CK_DLL_CTRL( biquad_ctrl_norm ); CK_DLL_CGET( biquad_cget_norm ); CK_DLL_CTRL( biquad_ctrl_pregain ); CK_DLL_CGET( biquad_cget_pregain ); CK_DLL_CTRL( biquad_ctrl_eqzs ); CK_DLL_CGET( biquad_cget_eqzs ); CK_DLL_CTRL( biquad_ctrl_b0 ); CK_DLL_CGET( biquad_cget_b0 ); CK_DLL_CTRL( biquad_ctrl_b1 ); CK_DLL_CGET( biquad_cget_b1 ); CK_DLL_CTRL( biquad_ctrl_b2 ); CK_DLL_CGET( biquad_cget_b2 ); CK_DLL_CTRL( biquad_ctrl_a0 ); CK_DLL_CGET( biquad_cget_a0 ); CK_DLL_CTRL( biquad_ctrl_a1 ); CK_DLL_CGET( biquad_cget_a1 ); CK_DLL_CTRL( biquad_ctrl_a2 ); CK_DLL_CGET( biquad_cget_a2 ); // onepole CK_DLL_CTOR( onepole_ctor ); CK_DLL_DTOR( onepole_dtor ); CK_DLL_TICK( onepole_tick ); CK_DLL_CTRL( onepole_ctrl_pole ); // onezero CK_DLL_CTOR( onezero_ctor ); CK_DLL_DTOR( onezero_dtor ); CK_DLL_TICK( onezero_tick ); CK_DLL_CTRL( onezero_ctrl_zero ); // twopole CK_DLL_CTOR( twopole_ctor ); CK_DLL_DTOR( twopole_dtor ); CK_DLL_TICK( twopole_tick ); CK_DLL_CTRL( twopole_ctrl_freq ); CK_DLL_CTRL( twopole_ctrl_rad ); CK_DLL_CTRL( twopole_ctrl_norm ); // twozero CK_DLL_CTOR( twozero_ctor ); CK_DLL_DTOR( twozero_dtor ); CK_DLL_TICK( twozero_tick ); CK_DLL_CTRL( twozero_ctrl_freq ); CK_DLL_CTRL( twozero_ctrl_rad ); // gQ CK_DLL_CTOR( gQ_ctor ); CK_DLL_DTOR( gQ_dtor ); CK_DLL_TICK( gQ_tick ); CK_DLL_CTRL( gQ_ctrl_freq ); CK_DLL_CTRL( gQ_ctrl_rad ); // allpass CK_DLL_CTOR( allpass_ctor ); CK_DLL_DTOR( allpass_dtor ); CK_DLL_TICK( allpass_tick ); CK_DLL_PMSG( allpass_pmsg ); // delay CK_DLL_CTOR( delay_ctor ); CK_DLL_DTOR( delay_dtor ); CK_DLL_TICK( delay_tick ); CK_DLL_CTRL( delay_ctrl_delay ); CK_DLL_CTRL( delay_ctrl_max ); CK_DLL_CTRL( delay_ctrl_tap ); CK_DLL_CTRL( delay_ctrl_energy ); // delayA CK_DLL_CTOR( delayA_ctor ); CK_DLL_DTOR( delayA_dtor ); CK_DLL_TICK( delayA_tick ); CK_DLL_CTRL( delayA_ctrl_delay ); CK_DLL_CTRL( delayA_ctrl_max ); // delayL CK_DLL_CTOR( delayL_ctor ); CK_DLL_DTOR( delayL_dtor ); CK_DLL_TICK( delayL_tick ); CK_DLL_CTRL( delayL_ctrl_delay ); CK_DLL_CTRL( delayL_ctrl_max ); #endif chuck-1.2.0.8.dfsg/src/ugen_osc.cpp0000644000175000017500000014163210600421721015442 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_osc.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip L. Davidson (philipd@alumni.princeton.edu) // date: Summer 2004 //----------------------------------------------------------------------------- #include "ugen_osc.h" #include "chuck_type.h" #include "chuck_ugen.h" #include #include static t_CKUINT g_srate = 0; // for member data offset static t_CKUINT osc_offset_data = 0; //----------------------------------------------------------------------------- // name: osc_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY osc_query( Chuck_DL_Query * QUERY ) { // srate g_srate = QUERY->srate; // get the env Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; // register deprecate type_engine_register_deprecate( env, "osc", "Osc" ); type_engine_register_deprecate( env, "phasor", "Phasor" ); type_engine_register_deprecate( env, "sinosc", "SinOsc" ); type_engine_register_deprecate( env, "triosc", "TriOsc" ); type_engine_register_deprecate( env, "sawosc", "SawOsc" ); type_engine_register_deprecate( env, "pulseosc", "PulseOsc" ); type_engine_register_deprecate( env, "sqrosc", "SqrOsc" ); //--------------------------------------------------------------------- // init as base class: osc //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Osc", "UGen", env->global(), osc_ctor, osc_dtor, osc_tick, osc_pmsg ) ) return FALSE; // add member variable osc_offset_data = type_engine_import_mvar( env, "int", "@osc_data", FALSE ); if( osc_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: freq func = make_new_mfun( "float", "freq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", osc_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: period func = make_new_mfun( "dur", "period", osc_ctrl_period ); func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "period", osc_cget_period ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sfreq ( == freq ) func = make_new_mfun( "float", "sfreq", osc_ctrl_freq ); func->add_arg( "float", "hz" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: phase func = make_new_mfun( "float", "phase", osc_ctrl_phase ); func->add_arg( "float", "phase" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "phase", osc_cget_phase ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: sync func = make_new_mfun( "int", "sync", osc_ctrl_sync ); func->add_arg( "int", "type" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "sync", osc_cget_sync ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // phasor //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Phasor", "Osc", env->global(), NULL, NULL, osc_tick, NULL ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sinosc //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "SinOsc", "Osc", env->global(), NULL, NULL, sinosc_tick, NULL ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // triosc - triangle oscillator //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "TriOsc", "Osc", env->global(), NULL, NULL, triosc_tick, NULL ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sawosc - sawtooth oscillator ( 0 | 1 triangle wave ) //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "SawOsc", "TriOsc", env->global(), sawosc_ctor, NULL, NULL, NULL ) ) return FALSE; func = make_new_mfun( "float", "width", sawosc_ctrl_width ); func->add_arg( "float", "width" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // pulseosc - pulse-width oscillator //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "PulseOsc", "Osc", env->global(), NULL, NULL, pulseosc_tick, NULL ) ) return FALSE; func = make_new_mfun( "float", "width", osc_ctrl_width ); func->add_arg( "float", "width" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // sqrosc - square_wave oscillator ( 0.5 pulse ) //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "SqrOsc", "PulseOsc", env->global(), sqrosc_ctor, NULL, NULL, NULL ) ) return FALSE; func = make_new_mfun( "float", "width", sqrosc_ctrl_width ); func->add_arg( "float", "width" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); // include GenX!!! if( !genX_query( QUERY ) ) return FALSE; return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: struct Osc_Data // desc: ... //----------------------------------------------------------------------------- struct Osc_Data { t_CKFLOAT num; t_CKFLOAT freq; int sync; t_CKUINT srate; t_CKFLOAT width; t_CKFLOAT phase; Osc_Data() { num = 0.0; freq = 220.0; sync = 0; // internal width = 0.5; srate = g_srate; phase = 0.0; } }; //----------------------------------------------------------------------------- // name: osc_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( osc_ctor ) { Osc_Data * d = new Osc_Data; Chuck_DL_Return r; // return data to be used later OBJ_MEMBER_UINT(SELF, osc_offset_data) = (t_CKUINT)d; osc_ctrl_freq( SELF, &(d->freq), &r, SHRED ); } //----------------------------------------------------------------------------- // name: osc_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( osc_dtor ) { // get the data Osc_Data * data = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // delete delete data; // set to NULL OBJ_MEMBER_UINT(SELF, osc_offset_data) = 0; } //----------------------------------------------------------------------------- // name: osc_tick() // desc: ... // // basic osx is a phasor... // we use a duty-cycle rep ( 0 - 1 ) rather than angular ( 0 - TWOPI ) // sinusoidal oscillators are special // // (maybe) as a rule, we store external phase control values // so that we can have a smooth change back to internal control -pld // // technically this should happen even with external phase control // that we'd be in the right place when translating back to internal... // this was decidely inefficient and nit-picky. -pld // //----------------------------------------------------------------------------- CK_DLL_TICK( osc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // synch phase to input else if( d->sync == 1 ) { // set phase d->phase = in; // no update inc_phase = FALSE; } // fm synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output to current phase *out = (SAMPLE)d->phase; // check if( inc_phase ) { // step the phase. d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; } return TRUE; } //----------------------------------------------------------------------------- // name: sinosc_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( sinosc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync phase to input else if( d->sync == 1 ) { // set freq d->phase = in; inc_phase = FALSE; } // FM synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync phase to now // else if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // set output *out = (SAMPLE) ::sin( d->phase * TWO_PI ); if( inc_phase ) { // next phase d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; } return TRUE; } //----------------------------------------------------------------------------- // name: triosc_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( triosc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync phase to input else if( d->sync == 1 ) { // set freq d->phase = in; inc_phase = FALSE; } // FM synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync to now // if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // compute t_CKFLOAT phase = d->phase + .25; if( phase > 1.0 ) phase -= 1.0; if( phase < d->width ) *out = (SAMPLE) (d->width == 0.0) ? 1.0 : -1.0 + 2.0 * phase / d->width; else *out = (SAMPLE) (d->width == 1.0) ? 0 : 1.0 - 2.0 * (phase - d->width) / (1.0 - d->width); // advance internal phase if( inc_phase ) { d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; } return TRUE; } // sawosc_tick is tri_osc tick with width=0.0 or width=1.0 -pld //----------------------------------------------------------------------------- // name: pulseosc_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( pulseosc_tick ) { // get the data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; // if input if( ugen->m_num_src ) { // sync frequency to input if( d->sync == 0 ) { // set freq d->freq = in; // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync phase to input else if( d->sync == 1 ) { // set freq d->phase = in; inc_phase = FALSE; } // FM synthesis else if( d->sync == 2 ) { // set freq t_CKFLOAT freq = d->freq + in; // phase increment d->num = freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= floor( d->num ); else if( d->num <= 1.0 ) d->num += floor( d->num ); } // sync to now // if( d->sync == 3 ) // { // d->phase = now * d->num; // inc_phase = FALSE; // } } // compute *out = (SAMPLE) (d->phase < d->width) ? 1.0 : -1.0; // move phase if( inc_phase ) { d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; } return TRUE; } // sqrosc_tick is pulseosc_tick at width=0.5 -pld; //----------------------------------------------------------------------------- // name: osc_ctrl_freq() // desc: set oscillator frequency //----------------------------------------------------------------------------- CK_DLL_CTRL( osc_ctrl_freq ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data); // set freq d->freq = GET_CK_FLOAT(ARGS); // phase increment d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= ::floor( d->num ); // return RETURN->v_float = (t_CKFLOAT)d->freq; } //----------------------------------------------------------------------------- // name: osc_cget_freq() // desc: get oscillator frequency //----------------------------------------------------------------------------- CK_DLL_CGET( osc_cget_freq ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data); // return RETURN->v_float = (t_CKFLOAT)d->freq; } //----------------------------------------------------------------------------- // name: osc_ctrl_period() // desc: set oscillator period //----------------------------------------------------------------------------- CK_DLL_CTRL( osc_ctrl_period ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data); t_CKDUR period = GET_CK_DUR(ARGS); // test if( period == 0.0 ) d->freq = 0.0; // set freq else d->freq = 1 / (period / d->srate); d->num = d->freq / d->srate; // bound it if( d->num >= 1.0 ) d->num -= ::floor( d->num ); // return RETURN->v_dur = period; } //----------------------------------------------------------------------------- // name: osc_cget_period() // desc: get oscillator period //----------------------------------------------------------------------------- CK_DLL_CGET( osc_cget_period ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data); t_CKDUR period = 0; // get period if( d->freq != 0.0 ) period = 1 / d->freq * d->srate; // return RETURN->v_dur = period; } //----------------------------------------------------------------------------- // name: osc_ctrl_phase() // desc: set oscillator phase wrapped to ( 0 - 1 ) //----------------------------------------------------------------------------- CK_DLL_CTRL( osc_ctrl_phase ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // set freq d->phase = GET_CK_FLOAT(ARGS); //bound ( this could be set arbitrarily high or low ) if ( d->phase >= 1.0 || d->phase < 0.0 ) d->phase -= floor( d->num ); // return RETURN->v_float = (t_CKFLOAT)d->phase; } //----------------------------------------------------------------------------- // name: osc_cget_phase() // desc: get oscillator phase wrapped to ( 0 - 1 ) //----------------------------------------------------------------------------- CK_DLL_CGET( osc_cget_phase ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // return RETURN->v_float = (t_CKFLOAT)d->phase; } //----------------------------------------------------------------------------- // name: osc_ctrl_width() // desc: set width of active phase ( bound 0.0 - 1.0 ); //----------------------------------------------------------------------------- CK_DLL_CTRL( osc_ctrl_width ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // set freq d->width = GET_CK_FLOAT(ARGS); //bound ( this could be set arbitrarily high or low ) d->width = ck_max( 0.0, ck_min( 1.0, d->width ) ); // return RETURN->v_float = (t_CKFLOAT)d->width; } //----------------------------------------------------------------------------- // name: osc_cget_width() // desc: get width of active phase ( bound 0.0 - 1.0 ); //----------------------------------------------------------------------------- CK_DLL_CGET( osc_cget_width ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // return RETURN->v_float = (t_CKFLOAT)d->width; } //----------------------------------------------------------------------------- // name: sqrosc_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( sqrosc_ctor ) { Osc_Data * d = new Osc_Data; Chuck_DL_Return r; sqrosc_ctrl_width( SELF, &(d->width), &r, SHRED ); } //----------------------------------------------------------------------------- // name: sqrosc_ctrl_width() // desc: force width to 0.5; //----------------------------------------------------------------------------- CK_DLL_CTRL( sqrosc_ctrl_width ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // force value d->width = 0.5; // return RETURN->v_float = (t_CKFLOAT)d->width; } //----------------------------------------------------------------------------- // name: sawosc_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( sawosc_ctor ) { Osc_Data * d = new Osc_Data; Chuck_DL_Return r; sawosc_ctrl_width( SELF, &(d->width), &r, SHRED ); } //----------------------------------------------------------------------------- // name: sawosc_ctrl_width() // force width to 0.0 ( falling ) or 1.0 ( rising ) //----------------------------------------------------------------------------- CK_DLL_CTRL( sawosc_ctrl_width ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // set freq d->width = GET_CK_FLOAT(ARGS); //bound ( this could be set arbitrarily high or low ) d->width = ( d->width < 0.5 ) ? 0.0 : 1.0; //rising or falling // return RETURN->v_float = (t_CKFLOAT)d->width; } //----------------------------------------------------------------------------- // name: osc_ctrl_sync() // desc: select sync mode for oscillator //----------------------------------------------------------------------------- CK_DLL_CTRL( osc_ctrl_sync ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // set sync t_CKINT psync = d->sync; d->sync = GET_CK_INT(ARGS); // bound ( this could be set arbitrarily high or low ) if( d->sync < 0 || d->sync > 2 ) d->sync = 0; if( d->sync == 0 && psync != d->sync ) { // if we are switching to internal tick // we need to pre-advance the phase... // this is probably stupid. -pld d->phase += d->num; // keep the phase between 0 and 1 if( d->phase > 1.0 ) d->phase -= 1.0; } // return RETURN->v_int = (t_CKINT)d->sync; } //----------------------------------------------------------------------------- // name: osc_cget_sync() // desc: get sync mode for oscillator //----------------------------------------------------------------------------- CK_DLL_CGET( osc_cget_sync ) { // get data Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); // return RETURN->v_int = (t_CKINT)d->sync; } //----------------------------------------------------------------------------- // name: osc_pmsg() // desc: ... //----------------------------------------------------------------------------- CK_DLL_PMSG( osc_pmsg ) { Osc_Data * d = (Osc_Data *)OBJ_MEMBER_UINT(SELF, osc_offset_data ); if( !strcmp( MSG, "print" ) ) { fprintf( stdout, "SinOsc: (freq=%f)", d->freq ); return TRUE; } // didn't handle return FALSE; } //----------------------------------------------------------------------------- // file: ugen_genX.cpp // desc: thought it would be a good way to learn the fascinating innards of // ChucK by porting some of the classic lookup table functions and adding // a few new ones that might be of use. // mostly ported from RTcmix (all by WarpTable) // // author: Dan Trueman (dtrueman.princeton.edu) // date: Winter 2007 //----------------------------------------------------------------------------- // for member data offset static t_CKUINT genX_offset_data = 0; // for internal usage static void _transition( t_CKDOUBLE a, t_CKDOUBLE alpha, t_CKDOUBLE b, t_CKINT n, t_CKDOUBLE * output ); //----------------------------------------------------------------------------- // name: genX_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY genX_query( Chuck_DL_Query * QUERY ) { // srate g_srate = QUERY->srate; // get the env Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; //--------------------------------------------------------------------- // init as base class: genX //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "GenX", "UGen", env->global(), genX_ctor, genX_dtor, genX_tick, genX_pmsg ) ) return FALSE; // add member variable genX_offset_data = type_engine_import_mvar( env, "int", "@GenX_data", FALSE ); if( genX_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "lookup", genX_lookup ); //lookup table value func->add_arg( "float", "which" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float[]", "coefs", genX_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // gen5 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gen5", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", gen5_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // gen7 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gen7", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", gen7_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // gen9 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gen9", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", gen9_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // gen10 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gen10", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", gen10_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // gen17 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gen17", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", gen17_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // Curve //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "CurveTable", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", curve_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //--------------------------------------------------------------------- // Warp //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "WarpTable", "GenX", env->global(), NULL, NULL, genX_tick, NULL ) ) return FALSE; func = make_new_mfun( "float[]", "coefs", warp_coeffs ); //load table func->add_arg( "float", "v[]" ); if( !type_engine_import_mfun( env, func ) ) goto error; /* func = make_new_mfun( "float", "coefs", warp_coeffs ); //load table func->add_arg( "float", "asym" ); func->add_arg( "float", "sym" ); if( !type_engine_import_mfun( env, func ) ) goto error; */ // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: struct genX_Data // desc: ... //----------------------------------------------------------------------------- #define genX_tableSize 4096 #define genX_MAX_COEFFS 100 struct genX_Data { t_CKUINT genX_type; t_CKDOUBLE genX_table[genX_tableSize]; // gewang: was int t_CKINT sync; t_CKUINT srate; t_CKFLOAT xtemp; t_CKDOUBLE coeffs[genX_MAX_COEFFS]; genX_Data() { //initialize data here sync = 0; srate = g_srate; t_CKINT i; for( i=0; ixtemp), &r ); } //----------------------------------------------------------------------------- // name: genX_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( genX_dtor ) { // get the data genX_Data * data = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data ); // delete SAFE_DELETE(data); // set to NULL OBJ_MEMBER_UINT(SELF, genX_offset_data) = 0; } //----------------------------------------------------------------------------- // name: genX_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( genX_tick ) { // get the data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data ); Chuck_UGen * ugen = (Chuck_UGen *)SELF; t_CKBOOL inc_phase = TRUE; t_CKDOUBLE in_index = 0.0; t_CKDOUBLE scaled_index = 0.0; t_CKDOUBLE alpha = 0.0, omAlpha = 0.0; t_CKUINT lowIndex = 0, hiIndex = 0; t_CKDOUBLE outvalue = 0.0; // if input if( ugen->m_num_src ) { in_index = in; // gewang: moved this to here if( in_index < 0. ) in_index = -in_index; //scaled_index = (in_index + 1.) * 0.5 * genX_tableSize; //drive with oscillator, [-1, 1] scaled_index = in_index * genX_tableSize; //drive with phasor [0, 1] } else { scaled_index = 0.; } // set up interpolation parameters lowIndex = (t_CKUINT)scaled_index; hiIndex = lowIndex + 1; alpha = scaled_index - lowIndex; omAlpha = 1. - alpha; // check table index ranges while(lowIndex >= genX_tableSize) lowIndex -= genX_tableSize; while(hiIndex >= genX_tableSize) hiIndex -= genX_tableSize; // could just call // outvalue = genX_lookup(in_index);? // calculate output value with linear interpolation outvalue = d->genX_table[lowIndex]*omAlpha + d->genX_table[hiIndex]*alpha; // set output *out = (SAMPLE)outvalue; return TRUE; } //----------------------------------------------------------------------------- // name: genX_lookup() // desc: lookup call for all gens //----------------------------------------------------------------------------- CK_DLL_CTRL( genX_lookup ) { // get the data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data ); t_CKFLOAT in_index; t_CKFLOAT scaled_index; t_CKFLOAT alpha, omAlpha; t_CKUINT lowIndex, hiIndex; t_CKFLOAT outvalue; in_index = GET_NEXT_FLOAT(ARGS); // gewang: moved to here if (in_index < 0.) in_index = -in_index; scaled_index = in_index * (genX_tableSize - 1); //drive with phasor [0, 1] //set up interpolation parameters lowIndex = (t_CKUINT)scaled_index; hiIndex = lowIndex + 1; alpha = scaled_index - lowIndex; omAlpha = 1. - alpha; //check table index ranges while(lowIndex >= genX_tableSize) lowIndex -= genX_tableSize; while(hiIndex >= genX_tableSize) hiIndex -= genX_tableSize; //calculate output value with linear interpolation outvalue = d->genX_table[lowIndex]*omAlpha + d->genX_table[hiIndex]*alpha; RETURN->v_float = (t_CKFLOAT)outvalue; } //----------------------------------------------------------------------------- // name: gen5_coeffs() // desc: setup table for gen5 //----------------------------------------------------------------------------- CK_DLL_CTRL( gen5_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i = 0, j, k, l, size; t_CKFLOAT wmax, xmax=0.0, c, amp2, amp1, coeffs[genX_MAX_COEFFS]; Chuck_Array8 * in_args = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen10coeffs, %d\n", weights); if(in_args<0) return; size = in_args->size(); if(size >= genX_MAX_COEFFS) size = genX_MAX_COEFFS - 1; t_CKFLOAT v; for(t_CKUINT ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); coeffs[ii] = v; } amp2 = coeffs[0]; if (amp2 <= 0.0) amp2 = 0.000001; for(k = 1; k < size; k += 2) { amp1 = amp2; amp2 = coeffs[k+1]; if (amp2 <= 0.0) amp2 = 0.000001; j = i + 1; d->genX_table[i] = amp1; c = (t_CKFLOAT) pow((amp2/amp1),(1./(coeffs[k]*genX_tableSize))); i = (t_CKINT)((j - 1) + coeffs[k]*genX_tableSize); for(l = j; l < i; l++) { if(l < genX_tableSize) d->genX_table[l] = d->genX_table[l-1] * c; } } for(j = 0; j < genX_tableSize; j++) { if ((wmax = fabs(d->genX_table[j])) > xmax) xmax = wmax; // fprintf( stdout, "table current = %f\n", wmax); } // fprintf( stdout, "table max = %f\n", xmax); for(j = 0; j < genX_tableSize; j++) { d->genX_table[j] /= xmax; } // return RETURN->v_object = in_args; } //----------------------------------------------------------------------------- // name: gen7_coeffs() // desc: setup table for gen7 //----------------------------------------------------------------------------- CK_DLL_CTRL( gen7_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i=0, j, k, l, size; t_CKFLOAT wmax, xmax = 0.0, amp2, amp1, coeffs[genX_MAX_COEFFS]; Chuck_Array8 * in_args = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen10coeffs, %d\n", weights); if(in_args<0) return; size = in_args->size(); if(size >= genX_MAX_COEFFS) size = genX_MAX_COEFFS - 1; t_CKFLOAT v; for(t_CKUINT ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); coeffs[ii] = v; } amp2 = coeffs[0]; for (k = 1; k < size; k += 2) { amp1 = amp2; amp2 = coeffs[k + 1]; j = i + 1; i = (t_CKINT)(j + coeffs[k]*genX_tableSize - 1); for (l = j; l <= i; l++) { if (l <= genX_tableSize) d->genX_table[l - 1] = amp1 + (amp2 - amp1) * (double) (l - j) / (i - j + 1); } } for(j = 0; j < genX_tableSize; j++) { if ((wmax = fabs(d->genX_table[j])) > xmax) xmax = wmax; // fprintf( stdout, "table current = %f\n", wmax); } // fprintf( stdout, "table max = %f\n", xmax); for(j = 0; j < genX_tableSize; j++) { d->genX_table[j] /= xmax; } // return RETURN->v_object = in_args; } //----------------------------------------------------------------------------- // name: gen9_coeffs() // desc: setup table for gen9 //----------------------------------------------------------------------------- CK_DLL_CTRL( gen9_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i, j, size; t_CKDOUBLE wmax, xmax=0.0; t_CKFLOAT coeffs[genX_MAX_COEFFS]; Chuck_Array8 * weights = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen10coeffs, %d\n", weights); if(weights<0) return; size = weights->size(); if(size >= genX_MAX_COEFFS) size = genX_MAX_COEFFS - 1; t_CKFLOAT v; for(t_CKUINT ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); coeffs[ii] = v; } for(j = size - 1; j > 0; j -= 3) { if(coeffs[j - 1] != 0) { for(i = 0; i < genX_tableSize; i++) { t_CKDOUBLE val = sin(TWO_PI * ((t_CKDOUBLE) i / ((t_CKDOUBLE) (genX_tableSize) / coeffs[j - 2]) + coeffs[j] / 360.)); d->genX_table[i] += val * coeffs[j - 1]; } } } for(j = 0; j < genX_tableSize; j++) { if ((wmax = fabs(d->genX_table[j])) > xmax) xmax = wmax; // fprintf( stdout, "table current = %f\n", wmax); } // fprintf( stdout, "table max = %f\n", xmax); for(j = 0; j < genX_tableSize; j++) { d->genX_table[j] /= xmax; } // return RETURN->v_object = weights; } //----------------------------------------------------------------------------- // name: gen10_coeffs() // desc: setup table for gen10 //----------------------------------------------------------------------------- CK_DLL_CTRL( gen10_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i, j, size; t_CKDOUBLE wmax, xmax=0.0; Chuck_Array8 * weights = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen10coeffs, %d\n", weights); if(weights<0) return; size = weights->size(); if(size >= genX_MAX_COEFFS) size = genX_MAX_COEFFS - 1; t_CKFLOAT v; for(t_CKUINT ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); d->coeffs[ii] = v; } j = genX_MAX_COEFFS; while (j--) { if (d->coeffs[j] != 0) { for (i = 0; i < genX_tableSize; i++) { t_CKDOUBLE val = (t_CKDOUBLE) (TWO_PI * (t_CKDOUBLE) i / (genX_tableSize / (j + 1))); d->genX_table[i] += sin(val) * d->coeffs[j]; } } } for(j = 0; j < genX_tableSize; j++) { if ((wmax = fabs(d->genX_table[j])) > xmax) xmax = wmax; // fprintf( stdout, "table current = %f\n", wmax); } // fprintf( stdout, "table max = %f\n", xmax); for(j = 0; j < genX_tableSize; j++) { d->genX_table[j] /= xmax; } // return RETURN->v_object = weights; } //----------------------------------------------------------------------------- // name: gen17_coeffs() // desc: setup table for gen17 //----------------------------------------------------------------------------- CK_DLL_CTRL( gen17_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i, j, size; t_CKDOUBLE Tn, Tn1, Tn2, dg, x, wmax = 0.0, xmax = 0.0; t_CKFLOAT coeffs[genX_MAX_COEFFS]; Chuck_Array8 * weights = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen17coeffs, %d\n", weights); if(weights<0) return; size = weights->size(); if(size >= genX_MAX_COEFFS) size = genX_MAX_COEFFS - 1; dg = (t_CKDOUBLE) (genX_tableSize / 2. - .5); t_CKFLOAT v; for(t_CKUINT ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); coeffs[ii] = v; } for (i = 0; i < genX_tableSize; i++) { x = (t_CKDOUBLE)(i / dg - 1.); d->genX_table[i] = 0.0; Tn1 = 1.0; Tn = x; for (j = 0; j < size; j++) { d->genX_table[i] = coeffs[j] * Tn + d->genX_table[i]; Tn2 = Tn1; Tn1 = Tn; Tn = 2.0 * x * Tn1 - Tn2; } } for(j = 0; j < genX_tableSize; j++) { if ((wmax = fabs(d->genX_table[j])) > xmax) xmax = wmax; // fprintf( stdout, "table current = %f\n", wmax); } // fprintf( stdout, "table max = %f\n", xmax); for(j = 0; j < genX_tableSize; j++) { d->genX_table[j] /= xmax; // fprintf( stdout, "table current = %f\n", d->genX_table[j]); } // return RETURN->v_object = weights; } //----------------------------------------------------------------------------- // name: curve_coeffs() // desc: setup table for Curve // ported from RTcmix //----------------------------------------------------------------------------- #define MAX_CURVE_PTS 256 CK_DLL_CTRL( curve_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i, points, nargs, seglen = 0, len = genX_tableSize; t_CKDOUBLE factor, *ptr, xmax=0.0; t_CKDOUBLE time[MAX_CURVE_PTS], value[MAX_CURVE_PTS], alpha[MAX_CURVE_PTS]; t_CKFLOAT coeffs[genX_MAX_COEFFS]; t_CKUINT ii = 0; t_CKFLOAT v = 0.0; Chuck_Array8 * weights = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // fprintf(stdout, "calling gen17coeffs, %d\n", weights); if(weights<0) goto done; nargs = weights->size(); if (nargs < 5 || (nargs % 3) != 2) { // check number of args fprintf( stderr, "[chuck](via CurveTable): usage: \n size, time1, value1, curvature1, [ timeN-1, valueN-1, curvatureN-1, ] timeN, valueN)\n" ); goto done; } if ((nargs / 3) + 1 > MAX_CURVE_PTS) { fprintf(stderr, ("[chuck](via CurveTable): too many arguments.\n")); goto done; } for(ii = 0; iiget(ii, &v); // fprintf( stdout, "weight %d = %f...\n", ii, v ); coeffs[ii] = v; } if (coeffs[0] != 0.0) { fprintf(stderr, "[chuck](via CurveTable): first time must be zero.\n"); goto done; } for (i = points = 0; i < nargs; points++) { time[points] = (t_CKDOUBLE) coeffs[i++]; if (points > 0 && time[points] < time[points - 1]) goto time_err; value[points] = (t_CKDOUBLE) coeffs[i++]; if (i < nargs) alpha[points] = (t_CKDOUBLE) coeffs[i++]; } factor = (t_CKDOUBLE) (len - 1) / time[points - 1]; for (i = 0; i < points; i++) time[i] *= factor; ptr = d->genX_table; for (i = 0; i < points - 1; i++) { seglen = (t_CKINT) (floor(time[i + 1] + 0.5) - floor(time[i] + 0.5)) + 1; _transition(value[i], alpha[i], value[i + 1], seglen, ptr); ptr += seglen - 1; } done: // return RETURN->v_object = weights; return; time_err: fprintf(stderr, "[chuck](via CurveTable): times must be in ascending order.\n"); // return RETURN->v_object = weights; return; } static void _transition(t_CKDOUBLE a, t_CKDOUBLE alpha, t_CKDOUBLE b, t_CKINT n, t_CKDOUBLE *output) { t_CKINT i; t_CKDOUBLE delta, interval = 0.0; delta = b - a; if (n <= 1) { //warn("maketable (curve)", "Trying to transition over 1 array slot; " // "time between points is too short"); *output = a; return; } interval = 1.0 / (n - 1.0); if (alpha != 0.0) { t_CKDOUBLE denom = 1.0 / (1.0 - exp(alpha)); for (i = 0; i < n; i++) *output++ = (a + delta * (1.0 - exp((double) i * alpha * interval)) * denom); } else for (i = 0; i < n; i++) *output++ = a + delta * i * interval; } //----------------------------------------------------------------------------- // name: warp_coeffs() // desc: setup table for warp //----------------------------------------------------------------------------- CK_DLL_CTRL( warp_coeffs ) { // get data genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data); t_CKINT i = 0; t_CKFLOAT k_asym = 1.; t_CKFLOAT k_sym = 1.; // gewang: Chuck_Array8 * weights = (Chuck_Array8 *)GET_CK_OBJECT(ARGS); // check for size if( weights->size() != 2 ) { // error fprintf( stderr, "[chuck](via WarpTable): expects array of exactly 2 elements.\n" ); goto done; } weights->get( 0, &k_asym ); // (t_CKDOUBLE) GET_NEXT_FLOAT(ARGS); weights->get( 1, &k_sym ); // (t_CKDOUBLE) GET_NEXT_FLOAT(ARGS); for (i = 0; i < genX_tableSize; i++) { t_CKDOUBLE inval = (t_CKDOUBLE) i/(genX_tableSize - 1); if(k_asym == 1 && k_sym == 1) { d->genX_table[i] = inval; } else if(k_sym == 1) { d->genX_table[i] = _asymwarp(inval, k_asym); } else if(k_asym == 1) { d->genX_table[i] = _symwarp(inval, k_sym); } else { inval = _asymwarp(inval, k_asym); d->genX_table[i] = _symwarp(inval, k_sym); } // fprintf(stdout, "table %d = %f\n", i, d->genX_table[i]); } done: // return RETURN->v_object = weights; } t_CKDOUBLE _asymwarp(t_CKDOUBLE inval, t_CKDOUBLE k) { return (pow(k, inval) - 1.) / (k - 1.); } t_CKDOUBLE _symwarp(t_CKDOUBLE inval, t_CKDOUBLE k) { t_CKDOUBLE sym_warped; if(inval >= 0.5) { sym_warped = pow(2.*inval - 1., 1./k); return (sym_warped + 1.) * 0.5; } inval = 1. - inval; // for S curve sym_warped = pow(2.*inval - 1., 1./k); sym_warped = (sym_warped + 1.) * 0.5; return 1. - sym_warped; } // also do RTcmix "spline" on a rainy day //----------------------------------------------------------------------------- // name: genX_pmsg() // desc: ... //----------------------------------------------------------------------------- CK_DLL_PMSG( genX_pmsg ) { genX_Data * d = (genX_Data *)OBJ_MEMBER_UINT(SELF, genX_offset_data ); if( !strcmp( MSG, "print" ) ) { // fprintf( stdout, "genX:" ); return TRUE; } // didn't handle return FALSE; } //----------------------------------------------------------------------------- // name: genX_coeffs() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTRL( genX_coeffs ) { // nope fprintf( stderr, "[chuck](via GenX): .coeffs called on abstract base class!\n" ); // return RETURN->v_object = GET_NEXT_OBJECT(ARGS); return; } chuck-1.2.0.8.dfsg/src/ugen_osc.h0000644000175000017500000000650710600421721015110 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_osc.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip L. Davidson (philipd@alumni.princeton.edu) // date: Summer 2004 //----------------------------------------------------------------------------- #ifndef __UGEN_OSC_H__ #define __UGEN_OSC_H__ #include "chuck_dl.h" // query DLL_QUERY osc_query( Chuck_DL_Query * query ); // osc - base CK_DLL_CTOR( osc_ctor ); CK_DLL_DTOR( osc_dtor ); CK_DLL_TICK( osc_tick ); CK_DLL_PMSG( osc_pmsg ); CK_DLL_CTRL( osc_ctrl_freq ); CK_DLL_CGET( osc_cget_freq ); CK_DLL_CTRL( osc_ctrl_period ); CK_DLL_CGET( osc_cget_period ); CK_DLL_CTRL( osc_ctrl_phase ); CK_DLL_CGET( osc_cget_phase ); CK_DLL_CTRL( osc_ctrl_width ); CK_DLL_CGET( osc_cget_width ); CK_DLL_CTRL( osc_ctrl_sync ); CK_DLL_CGET( osc_cget_sync ); // sinosc CK_DLL_TICK( sinosc_tick ); // pulseosc CK_DLL_TICK( pulseosc_tick ); // triosc CK_DLL_TICK( triosc_tick ); // sawosc CK_DLL_CTOR( sawosc_ctor ); CK_DLL_CTRL( sawosc_ctrl_width ); // sqrosc CK_DLL_CTOR( sqrosc_ctor ); CK_DLL_CTRL( sqrosc_ctrl_width ); //----------------------------------------------------------------------------- // file: ugen_genX // desc: thought it would be a good way to learn the fascinating innards of // ChucK by porting some of the classic lookup table functions and adding // a few new ones that might be of use. // mostly ported from RTcmix (all by WarpTable) // // author: Dan Trueman (dtrueman.princeton.edu) // date: Winter 2007 //----------------------------------------------------------------------------- // called by xxx_query DLL_QUERY genX_query( Chuck_DL_Query * query ); // genX - base CK_DLL_CTOR( genX_ctor ); CK_DLL_DTOR( genX_dtor ); CK_DLL_TICK( genX_tick ); CK_DLL_PMSG( genX_pmsg ); CK_DLL_CTRL( genX_lookup ); CK_DLL_CTRL( genX_coeffs ); CK_DLL_CTRL( gen5_coeffs ); CK_DLL_CTRL( gen7_coeffs ); CK_DLL_CTRL( gen9_coeffs ); CK_DLL_CTRL( gen10_coeffs ); CK_DLL_CTRL( gen17_coeffs ); CK_DLL_CTRL( curve_coeffs ); CK_DLL_CTRL( warp_coeffs ); t_CKDOUBLE _asymwarp( t_CKDOUBLE inval, t_CKDOUBLE k ); t_CKDOUBLE _symwarp( t_CKDOUBLE inval, t_CKDOUBLE k ); #endif chuck-1.2.0.8.dfsg/src/ugen_stk.cpp0000644000175000017500000271536610600421721015474 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_stk.cpp // desc: import library for Synthesis ToolKit (STK) - Perry Cook + Gary Scavone // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // Ari Lazier (alazier@cs.princeton.edu) // Philip Davidson (philipd@cs.princeton.edu) // Mark Daly (mdaly@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "ugen_stk.h" #include "chuck_type.h" #include "util_math.h" #include #include #include #include //------------------------------------------------------------------------------ // name: union what // desc: the litmus //------------------------------------------------------------------------------ union what { long x; char y[sizeof(long)]; }; t_CKBOOL little_endian = FALSE; // static t_CKUINT g_srate = 0; // filter member data offset static t_CKUINT Instrmnt_offset_data = 0; //static t_CKUINT BandedWG_offset_data = 0; //static t_CKUINT BlowBotl_offset_data = 0; //static t_CKUINT BlowHole_offset_data = 0; //static t_CKUINT Bowed_offset_data = 0; //static t_CKUINT Brass_offset_data = 0; //static t_CKUINT Clarinet_offset_data = 0; //static t_CKUINT Flute_offset_data = 0; //static t_CKUINT Mandolin_offset_data = 0; //static t_CKUINT ModalBar_offset_data = 0; //static t_CKUINT Moog_offset_data = 0; //static t_CKUINT Saxofony_offset_data = 0; //static t_CKUINT Shakers_offset_data = 0; //static t_CKUINT Sitar_offset_data = 0; //static t_CKUINT StifKarp_offset_data = 0; //static t_CKUINT VoicForm_offset_data = 0; static t_CKUINT FM_offset_data = 0; //static t_CKUINT BeeThree_offset_data = 0; //static t_CKUINT FMVoices_offset_data = 0; //static t_CKUINT HevyMetl_offset_data = 0; //static t_CKUINT PercFlut_offset_data = 0; //static t_CKUINT Rhodey_offset_data = 0; //static t_CKUINT TubeBell_offset_data = 0; //static t_CKUINT Wurley_offset_data = 0; static t_CKUINT FormSwep_offset_data = 0; static t_CKUINT Delay_offset_data = 0; static t_CKUINT DelayA_offset_data = 0; static t_CKUINT DelayL_offset_data = 0; static t_CKUINT Echo_offset_data = 0; static t_CKUINT Envelope_offset_data = 0; // static t_CKUINT Envelope_offset_data = 0; static t_CKUINT BiQuad_offset_data = 0; static t_CKUINT FilterStk_offset_data = 0; static t_CKUINT OnePole_offset_data = 0; static t_CKUINT TwoPole_offset_data = 0; static t_CKUINT OneZero_offset_data = 0; static t_CKUINT TwoZero_offset_data = 0; static t_CKUINT PoleZero_offset_data = 0; static t_CKUINT JCRev_offset_data = 0; static t_CKUINT NRev_offset_data = 0; static t_CKUINT PRCRev_offset_data = 0; static t_CKUINT Chorus_offset_data = 0; static t_CKUINT Modulate_offset_data = 0; static t_CKUINT SubNoise_offset_data = 0; static t_CKUINT WvIn_offset_data = 0; //static t_CKUINT WaveLoop_offset_data = 0; static t_CKUINT WvOut_offset_data = 0; static t_CKUINT PitShift_offset_data = 0; static t_CKUINT BLT_offset_data = 0; static t_CKUINT JetTabl_offset_data = 0; static t_CKUINT Mesh2D_offset_data = 0; // SKINI /* SkiniIn SkiniMessage => while(skin.getnextmessage(msg)) msg - type, data parameters, time stamp SkiniOut.send( midi message ) horn ok please -> written at the back of trucks, always, makes no sense. */ // ADSR CK_DLL_CTOR( ADSR_ctor ); CK_DLL_DTOR( ADSR_dtor ); CK_DLL_TICK( ADSR_tick ); CK_DLL_PMSG( ADSR_pmsg ); CK_DLL_CTRL( ADSR_ctrl_attackTime ); CK_DLL_CTRL( ADSR_ctrl_attackRate ); CK_DLL_CTRL( ADSR_ctrl_decayTime ); CK_DLL_CTRL( ADSR_ctrl_decayRate ); CK_DLL_CTRL( ADSR_ctrl_sustainLevel ); CK_DLL_CTRL( ADSR_ctrl_releaseTime ); CK_DLL_CTRL( ADSR_ctrl_releaseRate ); CK_DLL_CTRL( ADSR_ctrl_set ); CK_DLL_CTRL( ADSR_ctrl_set2 ); CK_DLL_CGET( ADSR_cget_attackTime ); CK_DLL_CGET( ADSR_cget_attackRate ); CK_DLL_CGET( ADSR_cget_decayTime ); CK_DLL_CGET( ADSR_cget_decayRate ); CK_DLL_CGET( ADSR_cget_sustainLevel ); CK_DLL_CGET( ADSR_cget_releaseTime ); CK_DLL_CGET( ADSR_cget_releaseRate ); CK_DLL_CGET( ADSR_cget_state ); // BiQuad CK_DLL_CTOR( BiQuad_ctor ); CK_DLL_DTOR( BiQuad_dtor ); CK_DLL_TICK( BiQuad_tick ); CK_DLL_PMSG( BiQuad_pmsg ); CK_DLL_CTRL( BiQuad_ctrl_b2 ); CK_DLL_CTRL( BiQuad_ctrl_b1 ); CK_DLL_CTRL( BiQuad_ctrl_b0 ); CK_DLL_CTRL( BiQuad_ctrl_a2 ); CK_DLL_CTRL( BiQuad_ctrl_a1 ); CK_DLL_CGET( BiQuad_ctrl_a0 ); CK_DLL_CTRL( BiQuad_ctrl_pfreq ); CK_DLL_CTRL( BiQuad_ctrl_prad ); CK_DLL_CTRL( BiQuad_ctrl_zfreq ); CK_DLL_CTRL( BiQuad_ctrl_zrad ); CK_DLL_CTRL( BiQuad_ctrl_norm ); CK_DLL_CTRL( BiQuad_ctrl_eqzs ); CK_DLL_CGET( BiQuad_cget_b2 ); CK_DLL_CGET( BiQuad_cget_b1 ); CK_DLL_CGET( BiQuad_cget_b0 ); CK_DLL_CGET( BiQuad_cget_a2 ); CK_DLL_CGET( BiQuad_cget_a1 ); CK_DLL_CGET( BiQuad_cget_a0 ); CK_DLL_CTRL( BiQuad_cget_pfreq ); CK_DLL_CTRL( BiQuad_cget_prad ); CK_DLL_CTRL( BiQuad_cget_zfreq ); CK_DLL_CTRL( BiQuad_cget_zrad ); // Chorus CK_DLL_CTOR( Chorus_ctor ); CK_DLL_DTOR( Chorus_dtor ); CK_DLL_TICK( Chorus_tick ); CK_DLL_PMSG( Chorus_pmsg ); CK_DLL_CTRL( Chorus_ctrl_modDepth ); CK_DLL_CTRL( Chorus_ctrl_modFreq ); CK_DLL_CTRL( Chorus_ctrl_mix ); CK_DLL_CGET( Chorus_cget_modDepth ); CK_DLL_CGET( Chorus_cget_modFreq ); CK_DLL_CGET( Chorus_cget_mix ); // Delay CK_DLL_CTOR( Delay_ctor ); CK_DLL_DTOR( Delay_dtor ); CK_DLL_TICK( Delay_tick ); CK_DLL_PMSG( Delay_pmsg ); CK_DLL_CTRL( Delay_ctrl_delay ); CK_DLL_CTRL( Delay_ctrl_max ); CK_DLL_CGET( Delay_cget_delay ); CK_DLL_CGET( Delay_cget_max ); // DelayA CK_DLL_CTOR( DelayA_ctor ); CK_DLL_DTOR( DelayA_dtor ); CK_DLL_TICK( DelayA_tick ); CK_DLL_PMSG( DelayA_pmsg ); CK_DLL_CTRL( DelayA_ctrl_delay ); CK_DLL_CTRL( DelayA_ctrl_max ); CK_DLL_CGET( DelayA_cget_delay ); CK_DLL_CGET( DelayA_cget_max ); // DelayL CK_DLL_CTOR( DelayL_ctor ); CK_DLL_DTOR( DelayL_dtor ); CK_DLL_TICK( DelayL_tick ); CK_DLL_PMSG( DelayL_pmsg ); CK_DLL_CTRL( DelayL_ctrl_delay ); CK_DLL_CTRL( DelayL_ctrl_max ); CK_DLL_CGET( DelayL_cget_delay ); CK_DLL_CGET( DelayL_cget_max ); // Echo CK_DLL_CTOR( Echo_ctor ); CK_DLL_DTOR( Echo_dtor ); CK_DLL_TICK( Echo_tick ); CK_DLL_PMSG( Echo_pmsg ); CK_DLL_CTRL( Echo_ctrl_delay ); CK_DLL_CTRL( Echo_ctrl_max ); CK_DLL_CTRL( Echo_ctrl_mix ); CK_DLL_CGET( Echo_cget_delay ); CK_DLL_CGET( Echo_cget_max ); CK_DLL_CGET( Echo_cget_mix ); // Envelope CK_DLL_CTOR( Envelope_ctor ); CK_DLL_DTOR( Envelope_dtor ); CK_DLL_TICK( Envelope_tick ); CK_DLL_PMSG( Envelope_pmsg ); CK_DLL_CTRL( Envelope_ctrl_rate ); CK_DLL_CTRL( Envelope_ctrl_target ); CK_DLL_CTRL( Envelope_cget_target ); CK_DLL_CTRL( Envelope_ctrl_time ); CK_DLL_CTRL( Envelope_ctrl_duration ); CK_DLL_CTRL( Envelope_ctrl_value ); CK_DLL_CTRL( Envelope_cget_value ); CK_DLL_CTRL( Envelope_ctrl_keyOn0 ); CK_DLL_CTRL( Envelope_ctrl_keyOn ); CK_DLL_CTRL( Envelope_ctrl_keyOff0 ); CK_DLL_CTRL( Envelope_ctrl_keyOff ); CK_DLL_CGET( Envelope_cget_rate ); CK_DLL_CGET( Envelope_cget_target ); CK_DLL_CGET( Envelope_cget_time ); CK_DLL_CGET( Envelope_cget_duration ); CK_DLL_CGET( Envelope_cget_value ); // FilterStk (originally Filter) CK_DLL_CTOR( FilterStk_ctor ); CK_DLL_DTOR( FilterStk_dtor ); CK_DLL_TICK( FilterStk_tick ); CK_DLL_PMSG( FilterStk_pmsg ); CK_DLL_CTRL( FilterStk_ctrl_coefs ); CK_DLL_CGET( FilterStk_cget_coefs ); // OnePole CK_DLL_CTOR( OnePole_ctor ); CK_DLL_DTOR( OnePole_dtor ); CK_DLL_TICK( OnePole_tick ); CK_DLL_PMSG( OnePole_pmsg ); CK_DLL_CTRL( OnePole_ctrl_a1 ); CK_DLL_CTRL( OnePole_ctrl_b0 ); CK_DLL_CTRL( OnePole_ctrl_pole ); CK_DLL_CGET( OnePole_cget_a1 ); CK_DLL_CGET( OnePole_cget_b0 ); CK_DLL_CGET( OnePole_cget_pole ); // TwoPole CK_DLL_CTOR( TwoPole_ctor ); CK_DLL_DTOR( TwoPole_dtor ); CK_DLL_TICK( TwoPole_tick ); CK_DLL_PMSG( TwoPole_pmsg ); CK_DLL_CTRL( TwoPole_ctrl_a1 ); CK_DLL_CTRL( TwoPole_ctrl_a2 ); CK_DLL_CTRL( TwoPole_ctrl_b0 ); CK_DLL_CTRL( TwoPole_ctrl_freq ); CK_DLL_CTRL( TwoPole_ctrl_radius ); CK_DLL_CTRL( TwoPole_ctrl_norm ); CK_DLL_CGET( TwoPole_cget_a1 ); CK_DLL_CGET( TwoPole_cget_a2 ); CK_DLL_CGET( TwoPole_cget_b0 ); CK_DLL_CGET( TwoPole_cget_freq ); CK_DLL_CGET( TwoPole_cget_radius ); CK_DLL_CGET( TwoPole_cget_norm ); // OneZero CK_DLL_CTOR( OneZero_ctor ); CK_DLL_DTOR( OneZero_dtor ); CK_DLL_TICK( OneZero_tick ); CK_DLL_PMSG( OneZero_pmsg ); CK_DLL_CTRL( OneZero_ctrl_zero ); CK_DLL_CTRL( OneZero_ctrl_b0 ); CK_DLL_CTRL( OneZero_ctrl_b1 ); CK_DLL_CGET( OneZero_cget_zero ); CK_DLL_CGET( OneZero_cget_b0 ); CK_DLL_CGET( OneZero_cget_b1 ); // TwoZero CK_DLL_CTOR( TwoZero_ctor ); CK_DLL_DTOR( TwoZero_dtor ); CK_DLL_TICK( TwoZero_tick ); CK_DLL_PMSG( TwoZero_pmsg ); CK_DLL_CTRL( TwoZero_ctrl_b0 ); CK_DLL_CTRL( TwoZero_ctrl_b1 ); CK_DLL_CTRL( TwoZero_ctrl_b2 ); CK_DLL_CTRL( TwoZero_ctrl_freq ); CK_DLL_CTRL( TwoZero_ctrl_radius ); CK_DLL_CGET( TwoZero_cget_b0 ); CK_DLL_CGET( TwoZero_cget_b1 ); CK_DLL_CGET( TwoZero_cget_b2 ); CK_DLL_CGET( TwoZero_cget_freq ); CK_DLL_CGET( TwoZero_cget_radius ); // PoleZero CK_DLL_CTOR( PoleZero_ctor ); CK_DLL_DTOR( PoleZero_dtor ); CK_DLL_TICK( PoleZero_tick ); CK_DLL_PMSG( PoleZero_pmsg ); CK_DLL_CTRL( PoleZero_ctrl_a1 ); CK_DLL_CTRL( PoleZero_ctrl_b0 ); CK_DLL_CTRL( PoleZero_ctrl_b1 ); CK_DLL_CTRL( PoleZero_ctrl_blockZero ); CK_DLL_CTRL( PoleZero_ctrl_allpass ); CK_DLL_CGET( PoleZero_cget_a1 ); CK_DLL_CGET( PoleZero_cget_b0 ); CK_DLL_CGET( PoleZero_cget_b1 ); CK_DLL_CGET( PoleZero_cget_blockZero ); CK_DLL_CGET( PoleZero_cget_allpass ); // Noise CK_DLL_CTOR( Noise_ctor ); CK_DLL_DTOR( Noise_dtor ); CK_DLL_TICK( Noise_tick ); CK_DLL_PMSG( Noise_pmsg ); CK_DLL_CTRL( Noise_ctrl_seed ); CK_DLL_CGET( Noise_cget_seed ); // SubNoise CK_DLL_CTOR( SubNoise_ctor ); CK_DLL_DTOR( SubNoise_dtor ); CK_DLL_TICK( SubNoise_tick ); CK_DLL_PMSG( SubNoise_pmsg ); CK_DLL_CTRL( SubNoise_ctrl_rate ); CK_DLL_CGET( SubNoise_cget_rate ); // BLT CK_DLL_CTOR( BLT_ctor ); CK_DLL_DTOR( BLT_dtor ); CK_DLL_TICK( BLT_tick ); CK_DLL_PMSG( BLT_pmsg ); CK_DLL_CTRL( BLT_ctrl_phase ); CK_DLL_CGET( BLT_cget_phase ); CK_DLL_CTRL( BLT_ctrl_freq ); CK_DLL_CGET( BLT_cget_freq ); CK_DLL_CTRL( BLT_ctrl_harmonics ); CK_DLL_CGET( BLT_cget_harmonics ); // Blit CK_DLL_CTOR( Blit_ctor ); CK_DLL_DTOR( Blit_dtor ); CK_DLL_TICK( Blit_tick ); CK_DLL_PMSG( Blit_pmsg ); // BlitSaw CK_DLL_CTOR( BlitSaw_ctor ); CK_DLL_DTOR( BlitSaw_dtor ); CK_DLL_TICK( BlitSaw_tick ); CK_DLL_PMSG( BlitSaw_pmsg ); // BlitSquare CK_DLL_CTOR( BlitSquare_ctor ); CK_DLL_DTOR( BlitSquare_dtor ); CK_DLL_TICK( BlitSquare_tick ); CK_DLL_PMSG( BlitSquare_pmsg ); // JCRev CK_DLL_CTOR( JCRev_ctor ); CK_DLL_DTOR( JCRev_dtor ); CK_DLL_TICK( JCRev_tick ); CK_DLL_PMSG( JCRev_pmsg ); CK_DLL_CTRL( JCRev_ctrl_mix ); CK_DLL_CGET( JCRev_cget_mix ); // NRev CK_DLL_CTOR( NRev_ctor ); CK_DLL_DTOR( NRev_dtor ); CK_DLL_TICK( NRev_tick ); CK_DLL_PMSG( NRev_pmsg ); CK_DLL_CTRL( NRev_ctrl_mix ); CK_DLL_CGET( NRev_cget_mix ); // PRCRev CK_DLL_CTOR( PRCRev_ctor ); CK_DLL_DTOR( PRCRev_dtor ); CK_DLL_TICK( PRCRev_tick ); CK_DLL_PMSG( PRCRev_pmsg ); CK_DLL_CTRL( PRCRev_ctrl_mix ); CK_DLL_CGET( PRCRev_cget_mix ); // WaveLoop CK_DLL_CTOR( WaveLoop_ctor ); CK_DLL_DTOR( WaveLoop_dtor ); CK_DLL_TICK( WaveLoop_tick ); CK_DLL_PMSG( WaveLoop_pmsg ); CK_DLL_CTRL( WaveLoop_ctrl_freq ); CK_DLL_CTRL( WaveLoop_ctrl_rate ); CK_DLL_CTRL( WaveLoop_ctrl_phase ); CK_DLL_CTRL( WaveLoop_ctrl_phaseOffset ); CK_DLL_CTRL( WaveLoop_ctrl_path ); CK_DLL_CGET( WaveLoop_cget_freq ); CK_DLL_CGET( WaveLoop_cget_rate ); CK_DLL_CGET( WaveLoop_cget_phase ); CK_DLL_CGET( WaveLoop_cget_phaseOffset ); CK_DLL_CGET( WaveLoop_cget_path ); // WvIn CK_DLL_CTOR( WvIn_ctor ); CK_DLL_DTOR( WvIn_dtor ); CK_DLL_TICK( WvIn_tick ); CK_DLL_PMSG( WvIn_pmsg ); CK_DLL_CTRL( WvIn_ctrl_rate ); CK_DLL_CTRL( WvIn_ctrl_path ); CK_DLL_CGET( WvIn_cget_rate ); CK_DLL_CGET( WvIn_cget_path ); // WvOut CK_DLL_CTOR( WvOut_ctor ); CK_DLL_DTOR( WvOut_dtor ); CK_DLL_TICK( WvOut_tick ); CK_DLL_PMSG( WvOut_pmsg ); CK_DLL_CTRL( WvOut_ctrl_filename ); CK_DLL_CTRL( WvOut_ctrl_matFilename ); CK_DLL_CTRL( WvOut_ctrl_sndFilename ); CK_DLL_CTRL( WvOut_ctrl_wavFilename ); CK_DLL_CTRL( WvOut_ctrl_rawFilename ); CK_DLL_CTRL( WvOut_ctrl_aifFilename ); CK_DLL_CTRL( WvOut_ctrl_closeFile ); CK_DLL_CTRL( WvOut_ctrl_record ); CK_DLL_CTRL( WvOut_ctrl_autoPrefix ); CK_DLL_CGET( WvOut_cget_filename ); CK_DLL_CGET( WvOut_cget_record ); CK_DLL_CGET( WvOut_cget_autoPrefix ); // FM CK_DLL_CTOR( FM_ctor ); CK_DLL_DTOR( FM_dtor ); CK_DLL_TICK( FM_tick ); CK_DLL_PMSG( FM_pmsg ); CK_DLL_CTRL( FM_ctrl_freq ); CK_DLL_CTRL( FM_ctrl_noteOn ); CK_DLL_CTRL( FM_ctrl_noteOff ); CK_DLL_CTRL( FM_ctrl_modDepth ); CK_DLL_CTRL( FM_ctrl_modSpeed ); CK_DLL_CTRL( FM_ctrl_control1 ); CK_DLL_CTRL( FM_ctrl_control2 ); CK_DLL_CTRL( FM_ctrl_controlChange ); CK_DLL_CTRL( FM_ctrl_afterTouch ); CK_DLL_CGET( FM_cget_freq ); CK_DLL_CGET( FM_cget_modDepth ); CK_DLL_CGET( FM_cget_modSpeed ); CK_DLL_CGET( FM_cget_control1 ); CK_DLL_CGET( FM_cget_control2 ); CK_DLL_CGET( FM_cget_afterTouch ); // FormSwep CK_DLL_CTOR( FormSwep_ctor ); CK_DLL_DTOR( FormSwep_dtor ); CK_DLL_TICK( FormSwep_tick ); CK_DLL_PMSG( FormSwep_pmsg ); CK_DLL_CTRL( FormSwep_ctrl_frequency ); CK_DLL_CGET( FormSwep_cget_frequency ); CK_DLL_CTRL( FormSwep_ctrl_radius ); CK_DLL_CGET( FormSwep_cget_radius ); CK_DLL_CTRL( FormSwep_ctrl_gain ); CK_DLL_CGET( FormSwep_cget_gain ); CK_DLL_CTRL( FormSwep_ctrl_sweepRate ); CK_DLL_CTRL( FormSwep_ctrl_sweepTime ); CK_DLL_CGET( FormSwep_cget_sweepRate ); CK_DLL_CGET( FormSwep_cget_sweepTime ); // Modulate CK_DLL_CTOR( Modulate_ctor ); CK_DLL_DTOR( Modulate_dtor ); CK_DLL_TICK( Modulate_tick ); CK_DLL_PMSG( Modulate_pmsg ); CK_DLL_CTRL( Modulate_ctrl_vibratoGain ); CK_DLL_CTRL( Modulate_ctrl_vibratoRate ); CK_DLL_CTRL( Modulate_ctrl_randomGain ); CK_DLL_CGET( Modulate_cget_vibratoGain ); CK_DLL_CGET( Modulate_cget_vibratoRate ); CK_DLL_CGET( Modulate_cget_randomGain ); // PitShift CK_DLL_CTOR( PitShift_ctor ); CK_DLL_DTOR( PitShift_dtor ); CK_DLL_TICK( PitShift_tick ); CK_DLL_PMSG( PitShift_pmsg ); CK_DLL_CTRL( PitShift_ctrl_shift ); CK_DLL_CTRL( PitShift_ctrl_effectMix ); CK_DLL_CGET( PitShift_cget_shift ); CK_DLL_CGET( PitShift_cget_effectMix ); // Sampler CK_DLL_CTOR( Sampler_ctor ); CK_DLL_DTOR( Sampler_dtor ); CK_DLL_TICK( Sampler_tick ); CK_DLL_PMSG( Sampler_pmsg ); // Drummer CK_DLL_CTOR( Drummer_ctor ); CK_DLL_DTOR( Drummer_dtor ); CK_DLL_TICK( Drummer_tick ); CK_DLL_PMSG( Drummer_pmsg ); // Instrmnt CK_DLL_CTOR( Instrmnt_ctor ); CK_DLL_DTOR( Instrmnt_dtor ); CK_DLL_TICK( Instrmnt_tick ); CK_DLL_PMSG( Instrmnt_pmsg ); CK_DLL_CTRL( Instrmnt_ctrl_freq ); CK_DLL_CGET( Instrmnt_cget_freq ); CK_DLL_CTRL( Instrmnt_ctrl_noteOn ); CK_DLL_CTRL( Instrmnt_ctrl_noteOff ); CK_DLL_CTRL( Instrmnt_ctrl_controlChange ); // BandedWG CK_DLL_CTOR( BandedWG_ctor ); CK_DLL_DTOR( BandedWG_dtor ); CK_DLL_TICK( BandedWG_tick ); CK_DLL_PMSG( BandedWG_pmsg ); CK_DLL_CTRL( BandedWG_ctrl_bowPressure ); CK_DLL_CGET( BandedWG_cget_bowPressure ); CK_DLL_CTRL( BandedWG_ctrl_bowMotion ); CK_DLL_CGET( BandedWG_cget_bowMotion ); CK_DLL_CTRL( BandedWG_ctrl_strikePosition ); CK_DLL_CGET( BandedWG_cget_strikePosition ); CK_DLL_CTRL( BandedWG_ctrl_vibratoFreq ); CK_DLL_CGET( BandedWG_cget_vibratoFreq ); CK_DLL_CTRL( BandedWG_ctrl_modesGain ); CK_DLL_CGET( BandedWG_cget_modesGain ); CK_DLL_CTRL( BandedWG_ctrl_bowRate ); CK_DLL_CGET( BandedWG_cget_bowRate ); CK_DLL_CTRL( BandedWG_ctrl_preset ); CK_DLL_CGET( BandedWG_cget_preset ); CK_DLL_CTRL( BandedWG_ctrl_startBowing ); CK_DLL_CTRL( BandedWG_ctrl_stopBowing ); CK_DLL_CTRL( BandedWG_ctrl_pluck ); CK_DLL_CTRL( BandedWG_ctrl_noteOn ); CK_DLL_CTRL( BandedWG_ctrl_noteOff ); CK_DLL_CTRL( BandedWG_ctrl_freq ); CK_DLL_CGET( BandedWG_cget_freq ); CK_DLL_CTRL( BandedWG_ctrl_controlChange ); /* CK_DLL_CTRL( BandedWG_ctrl_aftertouch ); CK_DLL_CTRL( BandedWG_ctrl_bowTarget ); CK_DLL_CTRL( BandedWG_ctrl_sustain ); CK_DLL_CTRL( BandedWG_ctrl_trackVelocity ); CK_DLL_CTRL( BandedWG_ctrl_portamento ); */ // BeeThree CK_DLL_CTOR( BeeThree_ctor ); CK_DLL_DTOR( BeeThree_dtor ); CK_DLL_TICK( BeeThree_tick ); CK_DLL_PMSG( BeeThree_pmsg ); CK_DLL_CTRL( BeeThree_ctrl_noteOn ); // BlowBotl CK_DLL_CTOR( BlowBotl_ctor ); CK_DLL_DTOR( BlowBotl_dtor ); CK_DLL_TICK( BlowBotl_tick ); CK_DLL_PMSG( BlowBotl_pmsg ); CK_DLL_CTRL( BlowBotl_ctrl_freq ); CK_DLL_CGET( BlowBotl_cget_freq ); CK_DLL_CTRL( BlowBotl_ctrl_noiseGain ); CK_DLL_CGET( BlowBotl_cget_noiseGain ); CK_DLL_CTRL( BlowBotl_ctrl_vibratoFreq ); CK_DLL_CGET( BlowBotl_cget_vibratoFreq ); CK_DLL_CTRL( BlowBotl_ctrl_vibratoGain ); CK_DLL_CGET( BlowBotl_cget_vibratoGain ); CK_DLL_CTRL( BlowBotl_ctrl_volume ); CK_DLL_CGET( BlowBotl_cget_volume ); CK_DLL_CTRL( BlowBotl_ctrl_noteOn ); CK_DLL_CTRL( BlowBotl_ctrl_noteOff ); CK_DLL_CTRL( BlowBotl_ctrl_controlChange ); CK_DLL_CTRL( BlowBotl_ctrl_startBlowing ); CK_DLL_CTRL( BlowBotl_ctrl_stopBlowing ); CK_DLL_CTRL( BlowBotl_ctrl_rate ); CK_DLL_CGET( BlowBotl_cget_rate ); // BlowHole CK_DLL_CTOR( BlowHole_ctor ); CK_DLL_DTOR( BlowHole_dtor ); CK_DLL_TICK( BlowHole_tick ); CK_DLL_PMSG( BlowHole_pmsg ); CK_DLL_CTRL( BlowHole_ctrl_freq ); CK_DLL_CGET( BlowHole_cget_freq ); CK_DLL_CTRL( BlowHole_ctrl_reed ); CK_DLL_CGET( BlowHole_cget_reed ); CK_DLL_CTRL( BlowHole_ctrl_noiseGain ); CK_DLL_CGET( BlowHole_cget_noiseGain ); CK_DLL_CTRL( BlowHole_ctrl_tonehole ); CK_DLL_CGET( BlowHole_cget_tonehole ); CK_DLL_CTRL( BlowHole_ctrl_vent ); CK_DLL_CGET( BlowHole_cget_vent ); CK_DLL_CTRL( BlowHole_ctrl_pressure ); CK_DLL_CGET( BlowHole_cget_pressure ); CK_DLL_CTRL( BlowHole_ctrl_noteOn ); CK_DLL_CTRL( BlowHole_ctrl_noteOff ); CK_DLL_CTRL( BlowHole_ctrl_controlChange ); CK_DLL_CTRL( BlowHole_ctrl_startBlowing ); CK_DLL_CTRL( BlowHole_ctrl_stopBlowing ); CK_DLL_CTRL( BlowHole_ctrl_rate ); CK_DLL_CGET( BlowHole_cget_rate ); // Bowed CK_DLL_CTOR( Bowed_ctor ); CK_DLL_DTOR( Bowed_dtor ); CK_DLL_TICK( Bowed_tick ); CK_DLL_PMSG( Bowed_pmsg ); CK_DLL_CTRL( Bowed_ctrl_freq ); CK_DLL_CGET( Bowed_cget_freq ); CK_DLL_CTRL( Bowed_ctrl_bowPressure ); CK_DLL_CGET( Bowed_cget_bowPressure ); CK_DLL_CTRL( Bowed_ctrl_bowPos ); CK_DLL_CGET( Bowed_cget_bowPos ); CK_DLL_CTRL( Bowed_ctrl_vibratoFreq ); CK_DLL_CGET( Bowed_cget_vibratoFreq ); CK_DLL_CTRL( Bowed_ctrl_vibratoGain ); CK_DLL_CGET( Bowed_cget_vibratoGain ); CK_DLL_CTRL( Bowed_ctrl_volume ); CK_DLL_CGET( Bowed_cget_volume ); CK_DLL_CTRL( Bowed_ctrl_noteOn ); CK_DLL_CTRL( Bowed_ctrl_noteOff ); CK_DLL_CTRL( Bowed_ctrl_controlChange ); CK_DLL_CTRL( Bowed_ctrl_startBowing ); CK_DLL_CTRL( Bowed_ctrl_stopBowing ); CK_DLL_CTRL( Bowed_ctrl_rate ); CK_DLL_CGET( Bowed_cget_rate ); // BowTabl CK_DLL_CTOR( BowTabl_ctor ); CK_DLL_DTOR( BowTabl_dtor ); CK_DLL_TICK( BowTabl_tick ); CK_DLL_PMSG( BowTabl_pmsg ); CK_DLL_CTRL( BowTabl_ctrl_offset ); CK_DLL_CTRL( BowTabl_ctrl_slope ); // Brass CK_DLL_CTOR( Brass_ctor ); CK_DLL_DTOR( Brass_dtor ); CK_DLL_TICK( Brass_tick ); CK_DLL_PMSG( Brass_pmsg ); CK_DLL_CTRL( Brass_ctrl_freq ); CK_DLL_CGET( Brass_cget_freq ); CK_DLL_CTRL( Brass_ctrl_lip ); CK_DLL_CGET( Brass_cget_lip ); CK_DLL_CTRL( Brass_ctrl_slide ); CK_DLL_CGET( Brass_cget_slide ); CK_DLL_CTRL( Brass_ctrl_vibratoFreq ); CK_DLL_CGET( Brass_cget_vibratoFreq ); CK_DLL_CTRL( Brass_ctrl_vibratoGain ); CK_DLL_CGET( Brass_cget_vibratoGain ); CK_DLL_CTRL( Brass_ctrl_volume ); CK_DLL_CGET( Brass_cget_volume ); CK_DLL_CTRL( Brass_ctrl_clear ); CK_DLL_CTRL( Brass_ctrl_noteOn ); CK_DLL_CTRL( Brass_ctrl_noteOff ); CK_DLL_CTRL( Brass_ctrl_controlChange ); CK_DLL_CTRL( Brass_ctrl_startBlowing ); CK_DLL_CTRL( Brass_ctrl_stopBlowing ); CK_DLL_CTRL( Brass_ctrl_rate ); CK_DLL_CGET( Brass_cget_rate ); // Clarinet CK_DLL_CTOR( Clarinet_ctor ); CK_DLL_DTOR( Clarinet_dtor ); CK_DLL_TICK( Clarinet_tick ); CK_DLL_PMSG( Clarinet_pmsg ); CK_DLL_CTRL( Clarinet_ctrl_freq ); CK_DLL_CGET( Clarinet_cget_freq ); CK_DLL_CTRL( Clarinet_ctrl_reed ); CK_DLL_CGET( Clarinet_cget_reed ); CK_DLL_CTRL( Clarinet_ctrl_noiseGain ); CK_DLL_CGET( Clarinet_cget_noiseGain ); CK_DLL_CTRL( Clarinet_ctrl_vibratoFreq ); CK_DLL_CGET( Clarinet_cget_vibratoFreq ); CK_DLL_CTRL( Clarinet_ctrl_vibratoGain ); CK_DLL_CGET( Clarinet_cget_vibratoGain ); CK_DLL_CTRL( Clarinet_ctrl_pressure ); CK_DLL_CGET( Clarinet_cget_pressure ); CK_DLL_CTRL( Clarinet_ctrl_clear ); CK_DLL_CTRL( Clarinet_ctrl_noteOn ); CK_DLL_CTRL( Clarinet_ctrl_noteOff ); CK_DLL_CTRL( Clarinet_ctrl_startBlowing ); CK_DLL_CTRL( Clarinet_ctrl_stopBlowing ); CK_DLL_CTRL( Clarinet_ctrl_rate ); CK_DLL_CGET( Clarinet_cget_rate ); CK_DLL_CTRL( Clarinet_ctrl_controlChange ); // Flute CK_DLL_CTOR( Flute_ctor ); CK_DLL_DTOR( Flute_dtor ); CK_DLL_TICK( Flute_tick ); CK_DLL_PMSG( Flute_pmsg ); CK_DLL_CTRL( Flute_ctrl_freq ); CK_DLL_CGET( Flute_cget_freq ); CK_DLL_CTRL( Flute_ctrl_jetDelay ); CK_DLL_CGET( Flute_cget_jetDelay ); CK_DLL_CTRL( Flute_ctrl_jetReflection ); CK_DLL_CGET( Flute_cget_jetReflection ); CK_DLL_CTRL( Flute_ctrl_endReflection ); CK_DLL_CGET( Flute_cget_endReflection ); CK_DLL_CTRL( Flute_ctrl_noiseGain ); CK_DLL_CGET( Flute_cget_noiseGain ); CK_DLL_CTRL( Flute_ctrl_vibratoFreq ); CK_DLL_CGET( Flute_cget_vibratoFreq ); CK_DLL_CTRL( Flute_ctrl_vibratoGain ); CK_DLL_CGET( Flute_cget_vibratoGain ); CK_DLL_CTRL( Flute_ctrl_pressure ); CK_DLL_CGET( Flute_cget_pressure ); CK_DLL_CTRL( Flute_ctrl_clear ); CK_DLL_CTRL( Flute_ctrl_noteOn ); CK_DLL_CTRL( Flute_ctrl_noteOff ); CK_DLL_CTRL( Flute_ctrl_controlChange ); CK_DLL_CTRL( Flute_ctrl_startBlowing ); CK_DLL_CTRL( Flute_ctrl_stopBlowing ); CK_DLL_CTRL( Flute_ctrl_rate ); CK_DLL_CGET( Flute_cget_rate ); // FMVoices CK_DLL_CTOR( FMVoices_ctor ); CK_DLL_DTOR( FMVoices_dtor ); CK_DLL_TICK( FMVoices_tick ); CK_DLL_PMSG( FMVoices_pmsg ); CK_DLL_CTRL( FMVoices_ctrl_vowel ); CK_DLL_CTRL( FMVoices_cget_vowel ); CK_DLL_CTRL( FMVoices_ctrl_spectralTilt ); CK_DLL_CTRL( FMVoices_cget_spectralTilt ); CK_DLL_CTRL( FMVoices_ctrl_adsrTarget ); CK_DLL_CTRL( FMVoices_cget_adsrTarget ); // HevyMetl CK_DLL_CTOR( HevyMetl_ctor ); CK_DLL_DTOR( HevyMetl_dtor ); CK_DLL_TICK( HevyMetl_tick ); CK_DLL_PMSG( HevyMetl_pmsg ); // JetTabl CK_DLL_CTOR( JetTabl_ctor ); CK_DLL_DTOR( JetTabl_dtor ); CK_DLL_TICK( JetTabl_tick ); CK_DLL_PMSG( JetTabl_pmsg ); // Mandolin CK_DLL_CTOR( Mandolin_ctor ); CK_DLL_DTOR( Mandolin_dtor ); CK_DLL_TICK( Mandolin_tick ); CK_DLL_PMSG( Mandolin_pmsg ); CK_DLL_CTRL( Mandolin_ctrl_freq ); CK_DLL_CGET( Mandolin_cget_freq ); CK_DLL_CTRL( Mandolin_ctrl_pluckPos ); CK_DLL_CGET( Mandolin_cget_pluckPos ); CK_DLL_CTRL( Mandolin_ctrl_bodySize ); CK_DLL_CGET( Mandolin_cget_bodySize ); CK_DLL_CTRL( Mandolin_ctrl_stringDamping ); CK_DLL_CGET( Mandolin_cget_stringDamping ); CK_DLL_CTRL( Mandolin_ctrl_stringDetune ); CK_DLL_CGET( Mandolin_cget_stringDetune ); CK_DLL_CTRL( Mandolin_ctrl_controlChange ); CK_DLL_CTRL( Mandolin_ctrl_afterTouch ); CK_DLL_CTRL( Mandolin_ctrl_pluck ); CK_DLL_CTRL( Mandolin_ctrl_noteOn ); CK_DLL_CTRL( Mandolin_ctrl_noteOff ); CK_DLL_CTRL( Mandolin_ctrl_bodyIR ); CK_DLL_CGET( Mandolin_cget_bodyIR ); // Modal CK_DLL_CTOR( Modal_ctor ); CK_DLL_DTOR( Modal_dtor ); CK_DLL_TICK( Modal_tick ); CK_DLL_PMSG( Modal_pmsg ); CK_DLL_CTRL( Modal_ctrl_freq ); CK_DLL_CTRL( Modal_ctrl_masterGain ); CK_DLL_CTRL( Modal_ctrl_directGain ); CK_DLL_CTRL( Modal_ctrl_mode ); CK_DLL_CTRL( Modal_ctrl_modeRatio ); CK_DLL_CTRL( Modal_ctrl_modeRadius ); CK_DLL_CTRL( Modal_ctrl_modeGain ); CK_DLL_CTRL( Modal_ctrl_strike ); CK_DLL_CTRL( Modal_ctrl_damp ); CK_DLL_CTRL( Modal_ctrl_noteOn ); CK_DLL_CTRL( Modal_ctrl_noteOff ); // ModalBar CK_DLL_CTOR( ModalBar_ctor ); CK_DLL_DTOR( ModalBar_dtor ); CK_DLL_TICK( ModalBar_tick ); CK_DLL_PMSG( ModalBar_pmsg ); CK_DLL_CTRL( ModalBar_ctrl_strike ); CK_DLL_CTRL( ModalBar_ctrl_damp ); CK_DLL_CTRL( ModalBar_ctrl_clear ); CK_DLL_CTRL( ModalBar_ctrl_noteOn ); CK_DLL_CTRL( ModalBar_ctrl_noteOff ); CK_DLL_CTRL( ModalBar_ctrl_stickHardness ); CK_DLL_CGET( ModalBar_cget_stickHardness ); CK_DLL_CTRL( ModalBar_ctrl_strikePosition ); CK_DLL_CGET( ModalBar_cget_strikePosition ); CK_DLL_CTRL( ModalBar_ctrl_vibratoGain ); CK_DLL_CGET( ModalBar_cget_vibratoGain ); CK_DLL_CTRL( ModalBar_ctrl_vibratoFreq ); CK_DLL_CGET( ModalBar_cget_vibratoFreq ); CK_DLL_CTRL( ModalBar_ctrl_preset ); CK_DLL_CGET( ModalBar_cget_preset ); CK_DLL_CTRL( ModalBar_ctrl_freq ); CK_DLL_CGET( ModalBar_cget_freq ); CK_DLL_CTRL( ModalBar_ctrl_directGain ); CK_DLL_CGET( ModalBar_cget_directGain ); CK_DLL_CTRL( ModalBar_ctrl_masterGain ); CK_DLL_CGET( ModalBar_cget_masterGain ); CK_DLL_CTRL( ModalBar_ctrl_mode ); CK_DLL_CGET( ModalBar_cget_mode ); CK_DLL_CTRL( ModalBar_ctrl_modeRatio ); CK_DLL_CGET( ModalBar_cget_modeRatio ); CK_DLL_CTRL( ModalBar_ctrl_modeRadius ); CK_DLL_CGET( ModalBar_cget_modeRadius ); CK_DLL_CTRL( ModalBar_ctrl_modeGain ); CK_DLL_CGET( ModalBar_cget_modeGain ); CK_DLL_CTRL( ModalBar_ctrl_volume ); CK_DLL_CGET( ModalBar_cget_volume ); CK_DLL_CTRL( ModalBar_ctrl_controlChange ); // Moog CK_DLL_CTOR( Moog_ctor ); CK_DLL_DTOR( Moog_dtor ); CK_DLL_TICK( Moog_tick ); CK_DLL_PMSG( Moog_pmsg ); CK_DLL_CTRL( Moog_ctrl_freq ); CK_DLL_CTRL( Moog_ctrl_noteOn ); CK_DLL_CTRL( Moog_ctrl_modSpeed ); CK_DLL_CTRL( Moog_ctrl_modDepth ); CK_DLL_CTRL( Moog_ctrl_filterQ ); CK_DLL_CTRL( Moog_ctrl_filterSweepRate ); CK_DLL_CTRL( Moog_ctrl_afterTouch ); CK_DLL_CTRL( Moog_ctrl_vibratoFreq ); CK_DLL_CTRL( Moog_ctrl_vibratoGain ); CK_DLL_CTRL( Moog_ctrl_volume ); CK_DLL_CGET( Moog_cget_freq ); CK_DLL_CGET( Moog_cget_modSpeed ); CK_DLL_CGET( Moog_cget_modDepth ); CK_DLL_CGET( Moog_cget_filterQ ); CK_DLL_CGET( Moog_cget_filterSweepRate ); CK_DLL_CGET( Moog_cget_vibratoFreq ); CK_DLL_CGET( Moog_cget_vibratoGain ); CK_DLL_CGET( Moog_cget_volume ); CK_DLL_CTRL( Moog_ctrl_controlChange ); // PercFlut CK_DLL_CTOR( PercFlut_ctor ); CK_DLL_DTOR( PercFlut_dtor ); CK_DLL_TICK( PercFlut_tick ); CK_DLL_PMSG( PercFlut_pmsg ); CK_DLL_CTRL( PercFlut_ctrl_noteOn ); CK_DLL_CTRL( PercFlut_ctrl_freq ); CK_DLL_CGET( PercFlut_cget_freq ); // Plucked CK_DLL_CTOR( Plucked_ctor ); CK_DLL_DTOR( Plucked_dtor ); CK_DLL_TICK( Plucked_tick ); CK_DLL_PMSG( Plucked_pmsg ); CK_DLL_CTRL( Plucked_ctrl_freq ); CK_DLL_CTRL( Plucked_ctrl_pluck ); CK_DLL_CTRL( Plucked_ctrl_noteOn ); CK_DLL_CTRL( Plucked_ctrl_noteOff ); // PluckTwo CK_DLL_CTOR( PluckTwo_ctor ); CK_DLL_DTOR( PluckTwo_dtor ); CK_DLL_TICK( PluckTwo_tick ); CK_DLL_PMSG( PluckTwo_pmsg ); CK_DLL_CTRL( PluckTwo_ctrl_detune ); CK_DLL_CTRL( PluckTwo_ctrl_freq ); CK_DLL_CTRL( PluckTwo_ctrl_pluckPosition ); CK_DLL_CTRL( PluckTwo_ctrl_baseLoopGain ); CK_DLL_CTRL( PluckTwo_ctrl_pluck ); CK_DLL_CTRL( PluckTwo_ctrl_noteOn ); CK_DLL_CTRL( PluckTwo_ctrl_noteOff ); // ReedTabl CK_DLL_CTOR( ReedTabl_ctor ); CK_DLL_DTOR( ReedTabl_dtor ); CK_DLL_TICK( ReedTabl_tick ); CK_DLL_PMSG( ReedTabl_pmsg ); CK_DLL_CTRL( ReedTabl_ctrl_offset ); CK_DLL_CTRL( ReedTabl_ctrl_slope ); // Resonate CK_DLL_CTOR( Resonate_ctor ); CK_DLL_DTOR( Resonate_dtor ); CK_DLL_TICK( Resonate_tick ); CK_DLL_PMSG( Resonate_pmsg ); // Rhodey CK_DLL_CTOR( Rhodey_ctor ); CK_DLL_DTOR( Rhodey_dtor ); CK_DLL_TICK( Rhodey_tick ); CK_DLL_PMSG( Rhodey_pmsg ); CK_DLL_CTRL( Rhodey_ctrl_freq ); CK_DLL_CTRL( Rhodey_ctrl_noteOn ); CK_DLL_CTRL( Rhodey_ctrl_noteOff ); CK_DLL_CTRL( Rhodey_cget_freq ); // Saxofony CK_DLL_CTOR( Saxofony_ctor ); CK_DLL_DTOR( Saxofony_dtor ); CK_DLL_TICK( Saxofony_tick ); CK_DLL_PMSG( Saxofony_pmsg ); CK_DLL_CTRL( Saxofony_ctrl_freq ); CK_DLL_CGET( Saxofony_cget_freq ); CK_DLL_CTRL( Saxofony_ctrl_reed ); CK_DLL_CGET( Saxofony_cget_reed ); CK_DLL_CTRL( Saxofony_ctrl_aperture ); CK_DLL_CTRL( Saxofony_cget_aperture ); CK_DLL_CTRL( Saxofony_ctrl_noiseGain ); CK_DLL_CGET( Saxofony_cget_noiseGain ); CK_DLL_CTRL( Saxofony_ctrl_vibratoGain ); CK_DLL_CGET( Saxofony_cget_vibratoGain ); CK_DLL_CTRL( Saxofony_ctrl_vibratoFreq ); CK_DLL_CTRL( Saxofony_cget_vibratoFreq ); CK_DLL_CTRL( Saxofony_ctrl_blowPosition ); CK_DLL_CGET( Saxofony_cget_blowPosition ); CK_DLL_CTRL( Saxofony_ctrl_pressure ); CK_DLL_CGET( Saxofony_cget_pressure ); CK_DLL_CTRL( Saxofony_ctrl_controlChange ); CK_DLL_CTRL( Saxofony_ctrl_startBlowing ); CK_DLL_CTRL( Saxofony_ctrl_stopBlowing ); CK_DLL_CTRL( Saxofony_ctrl_clear ); CK_DLL_CTRL( Saxofony_ctrl_rate ); CK_DLL_CGET( Saxofony_cget_rate ); CK_DLL_CTRL( Saxofony_ctrl_noteOn ); CK_DLL_CTRL( Saxofony_ctrl_noteOff ); // Shakers CK_DLL_CTOR( Shakers_ctor ); CK_DLL_DTOR( Shakers_dtor ); CK_DLL_TICK( Shakers_tick ); CK_DLL_PMSG( Shakers_pmsg ); CK_DLL_CTRL( Shakers_ctrl_energy ); CK_DLL_CGET( Shakers_cget_energy ); CK_DLL_CTRL( Shakers_ctrl_decay ); CK_DLL_CGET( Shakers_cget_decay ); CK_DLL_CTRL( Shakers_ctrl_objects ); CK_DLL_CGET( Shakers_cget_objects ); CK_DLL_CTRL( Shakers_ctrl_which ); CK_DLL_CGET( Shakers_cget_which ); CK_DLL_CTRL( Shakers_ctrl_noteOn ); CK_DLL_CTRL( Shakers_ctrl_noteOff ); CK_DLL_CTRL( Shakers_ctrl_freq ); CK_DLL_CGET( Shakers_cget_freq ); CK_DLL_CTRL( Shakers_ctrl_controlChange ); // Simple CK_DLL_CTOR( Simple_ctor ); CK_DLL_DTOR( Simple_dtor ); CK_DLL_PMSG( Simple_pmsg ); CK_DLL_CTRL( Simple_ctrl_freq ); // SingWave CK_DLL_CTOR( SingWave_ctor ); CK_DLL_DTOR( SingWave_dtor ); CK_DLL_TICK( SingWave_tick ); CK_DLL_PMSG( SingWave_pmsg ); CK_DLL_CTRL( SingWave_ctrl_wavFilename ); CK_DLL_CTRL( SingWave_ctrl_rawFilename ); CK_DLL_CTRL( SingWave_ctrl_norm ); CK_DLL_CTRL( SingWave_ctrl_sweepRate ); CK_DLL_CTRL( SingWave_ctrl_freq ); CK_DLL_CTRL( SingWave_ctrl_vibratoRate ); CK_DLL_CTRL( SingWave_ctrl_vibratoGain ); CK_DLL_CTRL( SingWave_ctrl_randomGain ); CK_DLL_CTRL( SingWave_ctrl_gainTarget ); CK_DLL_CTRL( SingWave_ctrl_gainRate ); // Sitar CK_DLL_CTOR( Sitar_ctor ); CK_DLL_DTOR( Sitar_dtor ); CK_DLL_TICK( Sitar_tick ); CK_DLL_PMSG( Sitar_pmsg ); CK_DLL_CTRL( Sitar_ctrl_noteOn ); CK_DLL_CTRL( Sitar_ctrl_noteOff ); CK_DLL_CTRL( Sitar_ctrl_pluck ); CK_DLL_CTRL( Sitar_ctrl_clear ); CK_DLL_CTRL( Sitar_ctrl_freq ); CK_DLL_CTRL( Sitar_cget_freq ); // Sphere CK_DLL_CTOR( Sphere_ctor ); CK_DLL_DTOR( Sphere_dtor ); CK_DLL_TICK( Sphere_tick ); CK_DLL_PMSG( Sphere_pmsg ); CK_DLL_CTRL( Sphere_ctrl_radius ); CK_DLL_CTRL( Sphere_ctrl_mass ); // StifKarp CK_DLL_CTOR( StifKarp_ctor ); CK_DLL_DTOR( StifKarp_dtor ); CK_DLL_TICK( StifKarp_tick ); CK_DLL_PMSG( StifKarp_pmsg ); CK_DLL_CTRL( StifKarp_ctrl_pluck ); CK_DLL_CTRL( StifKarp_ctrl_clear ); CK_DLL_CTRL( StifKarp_ctrl_noteOn ); CK_DLL_CTRL( StifKarp_ctrl_noteOff ); CK_DLL_CTRL( StifKarp_ctrl_freq ); CK_DLL_CGET( StifKarp_cget_freq ); CK_DLL_CTRL( StifKarp_ctrl_pickupPosition ); CK_DLL_CGET( StifKarp_cget_pickupPosition ); CK_DLL_CTRL( StifKarp_ctrl_stretch ); CK_DLL_CGET( StifKarp_cget_stretch ); CK_DLL_CTRL( StifKarp_ctrl_sustain ); CK_DLL_CGET( StifKarp_cget_sustain ); CK_DLL_CTRL( StifKarp_ctrl_baseLoopGain ); CK_DLL_CGET( StifKarp_cget_baseLoopGain ); // TubeBell CK_DLL_CTOR( TubeBell_ctor ); CK_DLL_DTOR( TubeBell_dtor ); CK_DLL_TICK( TubeBell_tick ); CK_DLL_PMSG( TubeBell_pmsg ); CK_DLL_CTRL( TubeBell_ctrl_noteOn ); CK_DLL_CTRL( TubeBell_ctrl_freq ); CK_DLL_CGET( TubeBell_cget_freq ); // Voicer CK_DLL_CTOR( Voicer_ctor ); CK_DLL_DTOR( Voicer_dtor ); CK_DLL_TICK( Voicer_tick ); CK_DLL_PMSG( Voicer_pmsg ); // VoicForm CK_DLL_CTOR( VoicForm_ctor ); CK_DLL_DTOR( VoicForm_dtor ); CK_DLL_TICK( VoicForm_tick ); CK_DLL_PMSG( VoicForm_pmsg ); CK_DLL_CTRL( VoicForm_ctrl_voiceMix ); CK_DLL_CGET( VoicForm_cget_voiceMix ); CK_DLL_CTRL( VoicForm_ctrl_phoneme ); CK_DLL_CGET( VoicForm_cget_phoneme ); CK_DLL_CTRL( VoicForm_ctrl_vibratoFreq ); CK_DLL_CGET( VoicForm_cget_vibratoFreq ); CK_DLL_CTRL( VoicForm_ctrl_vibratoGain ); CK_DLL_CGET( VoicForm_cget_vibratoGain ); CK_DLL_CTRL( VoicForm_ctrl_loudness ); CK_DLL_CGET( VoicForm_cget_loudness ); CK_DLL_CTRL( VoicForm_ctrl_freq ); CK_DLL_CGET( VoicForm_cget_freq ); CK_DLL_CTRL( VoicForm_ctrl_noteOn ); CK_DLL_CTRL( VoicForm_ctrl_noteOff ); CK_DLL_CTRL( VoicForm_ctrl_speak ); CK_DLL_CTRL( VoicForm_ctrl_quiet ); CK_DLL_CTRL( VoicForm_ctrl_voiced ); CK_DLL_CGET( VoicForm_cget_voiced ); CK_DLL_CTRL( VoicForm_ctrl_unVoiced ); CK_DLL_CGET( VoicForm_cget_unVoiced ); CK_DLL_CTRL( VoicForm_ctrl_pitchSweepRate ); CK_DLL_CGET( VoicForm_cget_pitchSweepRate ); CK_DLL_CTRL( VoicForm_ctrl_selPhoneme ); CK_DLL_CGET( VoicForm_cget_selPhoneme ); // Whistle CK_DLL_CTOR( Whistle_ctor ); CK_DLL_DTOR( Whistle_dtor ); CK_DLL_TICK( Whistle_tick ); CK_DLL_PMSG( Whistle_pmsg ); CK_DLL_CTRL( Whistle_ctrl_freq ); CK_DLL_CTRL( Whistle_ctrl_startBlowing ); CK_DLL_CTRL( Whistle_ctrl_stopBlowing ); CK_DLL_CTRL( Whistle_ctrl_noteOn ); CK_DLL_CTRL( Whistle_ctrl_noteOff ); // Wurley CK_DLL_CTOR( Wurley_ctor ); CK_DLL_DTOR( Wurley_dtor ); CK_DLL_TICK( Wurley_tick ); CK_DLL_PMSG( Wurley_pmsg ); CK_DLL_CTRL( Wurley_ctrl_freq ); CK_DLL_CTRL( Wurley_ctrl_noteOn ); CK_DLL_CTRL( Wurley_ctrl_noteOff ); CK_DLL_CGET( Wurley_cget_freq ); // Instrmnt CK_DLL_CTOR( Instrmnt_ctor ); CK_DLL_DTOR( Instrmnt_dtor ); CK_DLL_TICK( Instrmnt_tick ); CK_DLL_PMSG( Instrmnt_pmsg ); CK_DLL_CTRL( Instrmnt_ctrl_freq ); // Mesh2D CK_DLL_CTOR( Mesh2D_ctor ); CK_DLL_DTOR( Mesh2D_dtor ); CK_DLL_TICK( Mesh2D_tick ); CK_DLL_PMSG( Mesh2D_pmsg ); //CK_DLL_CTRL( Mesh2D_ctrl_NY ); //CK_DLL_CTRL( Mesh2D_ctrl_NY ); //CK_DLL_CTRL( Mesh2D_ctrl_NY ); //CK_DLL_CTRL( Mesh2D_ctrl_NX ); //CK_DLL_CTRL( Mesh2D_ctrl_NX ); //CK_DLL_CTRL( Mesh2D_ctrl_NX ); CK_DLL_CTRL( Mesh2D_ctrl_decay ); // Reverb CK_DLL_CTOR( Reverb_ctor ); CK_DLL_DTOR( Reverb_dtor ); CK_DLL_TICK( Reverb_tick ); CK_DLL_PMSG( Reverb_pmsg ); CK_DLL_CTRL( Reverb_ctrl_effectMix ); // Socket CK_DLL_CTOR( Socket_ctor ); CK_DLL_DTOR( Socket_dtor ); CK_DLL_TICK( Socket_tick ); CK_DLL_PMSG( Socket_pmsg ); // Stk CK_DLL_CTOR( Stk_ctor ); CK_DLL_DTOR( Stk_dtor ); CK_DLL_TICK( Stk_tick ); CK_DLL_PMSG( Stk_pmsg ); CK_DLL_CTRL( Stk_ctrl_sampleRate ); CK_DLL_CTRL( Stk_ctrl_rawwavePath ); // Table CK_DLL_CTOR( Table_ctor ); CK_DLL_DTOR( Table_dtor ); CK_DLL_TICK( Table_tick ); CK_DLL_PMSG( Table_pmsg ); // TcpWvIn CK_DLL_CTOR( TcpWvIn_ctor ); CK_DLL_DTOR( TcpWvIn_dtor ); CK_DLL_TICK( TcpWvIn_tick ); CK_DLL_PMSG( TcpWvIn_pmsg ); // TcpWvOut CK_DLL_CTOR( TcpWvOut_ctor ); CK_DLL_DTOR( TcpWvOut_dtor ); CK_DLL_TICK( TcpWvOut_tick ); CK_DLL_PMSG( TcpWvOut_pmsg ); // Vector3D CK_DLL_CTOR( Vector3D_ctor ); CK_DLL_DTOR( Vector3D_dtor ); CK_DLL_TICK( Vector3D_tick ); CK_DLL_PMSG( Vector3D_pmsg ); CK_DLL_CTRL( Vector3D_ctrl_x ); CK_DLL_CTRL( Vector3D_ctrl_y ); CK_DLL_CTRL( Vector3D_ctrl_z ); // JetTable CK_DLL_CTOR( JetTabl_ctor ); CK_DLL_DTOR( JetTabl_dtor ); CK_DLL_TICK( JetTabl_tick ); CK_DLL_PMSG( JetTabl_pmsg ); // Mesh2D CK_DLL_CTOR( Mesh2D_ctor ); CK_DLL_DTOR( Mesh2D_dtor ); CK_DLL_TICK( Mesh2D_tick ); CK_DLL_PMSG( Mesh2D_pmsg ); CK_DLL_CTRL( Mesh2D_ctrl_nx ); CK_DLL_CTRL( Mesh2D_ctrl_ny ); CK_DLL_CTRL( Mesh2D_cget_nx ); CK_DLL_CTRL( Mesh2D_cget_ny ); CK_DLL_CTRL( Mesh2D_ctrl_input_position ); CK_DLL_CTRL( Mesh2D_cget_input_position ); CK_DLL_CTRL( Mesh2D_ctrl_decay ); CK_DLL_CTRL( Mesh2D_cget_decay ); CK_DLL_CTRL( Mesh2D_ctrl_note_on ); CK_DLL_CTRL( Mesh2D_ctrl_note_off ); CK_DLL_CTRL( Mesh2D_cget_energy ); CK_DLL_CTRL( Mesh2D_ctrl_control_change ); //----------------------------------------------------------------------------- // name: stk_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY stk_query( Chuck_DL_Query * QUERY ) { Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; // set srate Stk::setSampleRate( QUERY->srate ); // test for endian what w; w.x = 1; little_endian = (t_CKBOOL)w.y[0]; //! \sectionMain STK //! \section stk - instruments //------------------------------------------------------------------------ // begin Instrmnt ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "StkInstrument", "UGen", env->global(), Instrmnt_ctor, NULL, Instrmnt_tick, Instrmnt_pmsg ) ) return FALSE; // member variable Instrmnt_offset_data = type_engine_import_mvar ( env, "int", "@Instrmnt_data", FALSE ); if( Instrmnt_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "noteOn", Instrmnt_ctrl_noteOn ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noteOff", Instrmnt_ctrl_noteOff ); //! note off func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", Instrmnt_ctrl_freq ); //! frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", Instrmnt_cget_freq ); //! frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "controlChange", Instrmnt_ctrl_controlChange ); //! control change func->add_arg( "int", "ctrl" ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BandedWG ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BandedWG", "StkInstrument", env->global(), BandedWG_ctor, BandedWG_dtor, BandedWG_tick, BandedWG_pmsg ) ) return FALSE; // member variable // BandedWG_offset_data = type_engine_import_mvar ( env, "int", "@BandedWG_data", FALSE ); // if( BandedWG_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "pluck", BandedWG_ctrl_pluck ); //! pluck waveguide func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "startBowing", BandedWG_ctrl_startBowing ); //! startBowing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBowing", BandedWG_ctrl_stopBowing ); //! stopBowing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowRate", BandedWG_ctrl_bowRate ); //! strike bowRate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowRate", BandedWG_cget_bowRate ); //! strike bowRate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPressure", BandedWG_ctrl_bowPressure ); //! bowPressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPressure", BandedWG_cget_bowPressure ); //! bowPressure if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowMotion", BandedWG_ctrl_bowMotion ); //! bowMotion func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowMotion", BandedWG_cget_bowMotion ); //! bowMotion if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "integrationConstant", BandedWG_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "integrationConstant", BandedWG_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modesGain", BandedWG_ctrl_modesGain ); //! modesGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modesGain", BandedWG_cget_modesGain ); //! modesGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", BandedWG_ctrl_preset ); //! preset func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", BandedWG_cget_preset ); //! preset if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "strikePosition", BandedWG_ctrl_strikePosition ); //! strike Position func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "strikePosition", BandedWG_cget_strikePosition ); //! strike Position if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BlowBotl ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BlowBotl", "StkInstrument", env->global(), BlowBotl_ctor, BlowBotl_dtor, BlowBotl_tick, BlowBotl_pmsg ) ) return FALSE; // member variable // BlowBotl_offset_data = type_engine_import_mvar ( env, "int", "@BlowBotl_data", FALSE ); // if( BlowBotl_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "startBlowing", BlowBotl_ctrl_startBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", BlowBotl_ctrl_stopBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", BlowBotl_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", BlowBotl_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", BlowBotl_ctrl_noiseGain ); //! noiseGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", BlowBotl_cget_noiseGain ); //! noiseGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", BlowBotl_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", BlowBotl_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", BlowBotl_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", BlowBotl_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", BlowBotl_ctrl_volume ); //! volume func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", BlowBotl_cget_volume ); //! volume if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BlowHole ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BlowHole", "StkInstrument", env->global(), BlowHole_ctor, BlowHole_dtor, BlowHole_tick, BlowHole_pmsg ) ) return FALSE; // member variable // BlowHole_offset_data = type_engine_import_mvar ( env, "int", "@BlowHole_data", FALSE ); // if( BlowHole_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "startBlowing", BlowHole_ctrl_startBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", BlowHole_ctrl_stopBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vent", BlowHole_ctrl_vent ); //! vent frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vent", BlowHole_cget_vent ); //! vent frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "tonehole", BlowHole_ctrl_tonehole ); //! tonehole size func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "tonehole", BlowHole_cget_tonehole ); //! tonehole size if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "reed", BlowHole_ctrl_reed ); //! reed stiffness func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "reed", BlowHole_cget_reed ); //! reed stiffness if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", BlowHole_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", BlowHole_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", BlowHole_ctrl_noiseGain ); //! noise gain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", BlowHole_cget_noiseGain ); //! noise gain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", BlowHole_ctrl_pressure ); //! breath pressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", BlowHole_cget_pressure ); //! breath pressure if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Bowed ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Bowed", "StkInstrument", env->global(), Bowed_ctor, Bowed_dtor, Bowed_tick, Bowed_pmsg ) ) return FALSE; // member variable // Bowed_offset_data = type_engine_import_mvar ( env, "int", "@Bowed_data", FALSE ); // if( Bowed_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "startBowing", Bowed_ctrl_startBowing ); //! begin bowing instrument func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBowing", Bowed_ctrl_stopBowing ); //! stop bowing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPressure", Bowed_ctrl_bowPressure ); //! bowPressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPressure", Bowed_cget_bowPressure ); //! bowPressure if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPosition", Bowed_ctrl_bowPos ); //! bowPos func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bowPosition", Bowed_cget_bowPos ); //! bowPos if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Bowed_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Bowed_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Bowed_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Bowed_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Bowed_ctrl_volume ); //! volume func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Bowed_cget_volume ); //! volume if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Brass ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Brass", "StkInstrument", env->global(), Brass_ctor, Brass_dtor, Brass_tick, Brass_pmsg ) ) return FALSE; // member variable // Brass_offset_data = type_engine_import_mvar ( env, "int", "@Brass_data", FALSE ); // if( Brass_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "clear", Brass_ctrl_clear ); //! clear instrument func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "startBlowing", Brass_ctrl_startBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", Brass_ctrl_stopBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lip", Brass_ctrl_lip ); //! lip stiffness func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lip", Brass_cget_lip ); //! lip stiffness if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "slide", Brass_ctrl_slide ); //! slide func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "slide", Brass_cget_slide ); //! slide if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Brass_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Brass_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Brass_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Brass_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Brass_ctrl_volume ); //! volume func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Brass_cget_volume ); //! volume if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Brass_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Brass_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Clarinet ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Clarinet", "StkInstrument", env->global(), Clarinet_ctor, Clarinet_dtor, Clarinet_tick, Clarinet_pmsg ) ) return FALSE; // member variable // Clarinet_offset_data = type_engine_import_mvar ( env, "int", "@Clarinet_data", FALSE ); // if( Clarinet_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "clear", Clarinet_ctrl_clear ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "startBlowing", Clarinet_ctrl_startBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", Clarinet_ctrl_stopBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Clarinet_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Clarinet_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "reed", Clarinet_ctrl_reed); //! reed func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "reed", Clarinet_cget_reed); //! reed if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Clarinet_ctrl_noiseGain ); //! noiseGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Clarinet_cget_noiseGain ); //! noiseGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Clarinet_ctrl_vibratoFreq ); //! rvibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Clarinet_cget_vibratoFreq ); //! rvibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Clarinet_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Clarinet_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Clarinet_ctrl_pressure ); //! pressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Clarinet_cget_pressure ); //! pressure if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Flute ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Flute", "StkInstrument", env->global(), Flute_ctor, Flute_dtor, Flute_tick, Flute_pmsg ) ) return FALSE; // member variable // Flute_offset_data = type_engine_import_mvar ( env, "int", "@Flute_data", FALSE ); // if( Flute_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "clear", Flute_ctrl_clear ); //! clear func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "startBlowing", Flute_ctrl_startBlowing ); //! startBlowing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", Flute_ctrl_stopBlowing ); //! stopBlowing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Flute_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Flute_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "jetReflection", Flute_ctrl_jetReflection ); //! jet reflection func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "jetReflection", Flute_cget_jetReflection ); //! jet reflection if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "jetDelay", Flute_ctrl_jetDelay ); //! jet delay func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "jetDelay", Flute_cget_jetDelay ); //! jet delay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "endReflection", Flute_ctrl_endReflection ); //! end reflection func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "endReflection", Flute_cget_endReflection ); //! end reflection if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Flute_ctrl_noiseGain ); //! noiseGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Flute_cget_noiseGain ); //! noiseGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Flute_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Flute_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Flute_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Flute_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Flute_ctrl_pressure ); //! pressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Flute_cget_pressure ); //! pressure if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Mandolin ugen //------------------------------------------------------------------------ //! see \example mand-o-matic.ck if( !type_engine_import_ugen_begin( env, "Mandolin", "StkInstrument", env->global(), Mandolin_ctor, Mandolin_dtor, Mandolin_tick, Mandolin_pmsg ) ) return FALSE; // member variable // Mandolin_offset_data = type_engine_import_mvar ( env, "int", "@Mandolin_data", FALSE ); // if( Mandolin_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "pluck", Mandolin_ctrl_pluck ); //! pluck string with given amplitude func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pluckPos", Mandolin_ctrl_pluckPos ); //! set pluck position ( 0-1) along string func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pluckPos", Mandolin_cget_pluckPos ); //! set pluck position ( 0-1) along string if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bodySize", Mandolin_ctrl_bodySize ); //! modify instrument size func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "bodySize", Mandolin_cget_bodySize ); //! modify instrument size if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stringDamping", Mandolin_ctrl_stringDamping ); //! control string damping func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stringDamping", Mandolin_cget_stringDamping ); //! control string damping if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stringDetune", Mandolin_ctrl_stringDetune ); //! control detuning of string pair func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stringDetune", Mandolin_cget_stringDetune ); //! control detuning of string pair if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "afterTouch", Mandolin_ctrl_afterTouch ); //! aftertouch func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "bodyIR", Mandolin_ctrl_bodyIR ); //! read body impulse response func->add_arg( "string", "path" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "bodyIR", Mandolin_cget_bodyIR ); //! get path if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin ModalBar ugen //------------------------------------------------------------------------ //! see \example modalbot.ck if( !type_engine_import_ugen_begin( env, "ModalBar", "StkInstrument", env->global(), ModalBar_ctor, ModalBar_dtor, ModalBar_tick, ModalBar_pmsg ) ) return FALSE; // member variable // ModalBar_offset_data = type_engine_import_mvar ( env, "int", "@ModalBar_data", FALSE ); // if( ModalBar_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "strike", ModalBar_ctrl_strike ); //! strike bar func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "damp", ModalBar_ctrl_damp ); //! damp bar func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "clear", ModalBar_ctrl_clear ); //! clear func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", ModalBar_ctrl_preset ); //! choose preset func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", ModalBar_cget_preset ); //! choose preset if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stickHardness", ModalBar_ctrl_stickHardness ); //! set stickHardness func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stickHardness", ModalBar_cget_stickHardness ); //! set stickHardness if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "strikePosition", ModalBar_ctrl_strikePosition ); //! set strikePosition func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "strikePosition", ModalBar_cget_strikePosition ); //! set strikePosition if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", ModalBar_ctrl_vibratoGain ); //! set vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", ModalBar_cget_vibratoGain ); //! set vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", ModalBar_ctrl_vibratoFreq ); //! set vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", ModalBar_cget_vibratoFreq ); //! set vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "directGain", ModalBar_ctrl_directGain ); //! set directGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "directGain", ModalBar_cget_directGain ); //! set directGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "masterGain", ModalBar_ctrl_masterGain ); //! set masterGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "masterGain", ModalBar_cget_masterGain ); //! set masterGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "mode", ModalBar_ctrl_mode ); //! choose mode func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "mode", ModalBar_cget_mode ); //! choose mode if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeRatio", ModalBar_ctrl_modeRatio ); //! mode edit (modeRatio) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeRatio", ModalBar_cget_modeRatio ); //! mode edit (modeRatio) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeRadius", ModalBar_ctrl_modeRadius ); //! mode edit (modeRadius) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeRadius", ModalBar_cget_modeRadius ); //! mode edit (modeRadius) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeGain", ModalBar_ctrl_modeGain ); //! mode edit (modeGain) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modeGain", ModalBar_cget_modeGain ); //! mode edit (modeGain) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", ModalBar_ctrl_volume ); //! volume func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", ModalBar_cget_volume ); //! volume if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Moog ugen //------------------------------------------------------------------------ //! see \example moogie.ck if( !type_engine_import_ugen_begin( env, "Moog", "StkInstrument", env->global(), Moog_ctor, Moog_dtor, Moog_tick, Moog_pmsg ) ) return FALSE; // member variable // Moog_offset_data = type_engine_import_mvar ( env, "int", "@Moog_data", FALSE ); // if( Moog_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "lfoSpeed", Moog_ctrl_modSpeed ); //! modulation speed func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoSpeed", Moog_cget_modSpeed ); //! modulation speed if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoDepth", Moog_ctrl_modDepth ); //! modulation depth func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoDepth", Moog_cget_modDepth ); //! modulation depth if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modSpeed", Moog_ctrl_modSpeed ); //! modulation speed func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modSpeed", Moog_cget_modSpeed ); //! modulation speed if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modDepth", Moog_ctrl_modDepth ); //! modulation depth func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modDepth", Moog_cget_modDepth ); //! modulation depth if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "filterQ", Moog_ctrl_filterQ ); //! filter Q value func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "filterQ", Moog_cget_filterQ ); //! filter Q value if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "filterSweepRate", Moog_ctrl_filterSweepRate ); //! filter sweep rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "filterSweepRate", Moog_cget_filterSweepRate ); //! filter sweep rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "afterTouch", Moog_ctrl_afterTouch ); // aftertouch func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Moog_ctrl_volume ); //! volume func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "volume", Moog_cget_volume ); //! volume if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Moog_ctrl_vibratoFreq ); //! vibrato frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Moog_cget_vibratoFreq ); //! vibrato frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Moog_ctrl_vibratoGain ); //! vibrato gain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Moog_cget_vibratoGain ); //! vibrato gain if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Saxofony ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Saxofony", "StkInstrument", env->global(), Saxofony_ctor, Saxofony_dtor, Saxofony_tick, Saxofony_pmsg ) ) return FALSE; // member variable // Saxofony_offset_data = type_engine_import_mvar ( env, "int", "@Saxofony_data", FALSE ); // if( Saxofony_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "clear", Saxofony_ctrl_clear ); //! clear instrument func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "startBlowing", Saxofony_ctrl_startBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stopBlowing", Saxofony_ctrl_stopBlowing ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Saxofony_ctrl_rate ); //! rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Saxofony_cget_rate ); //! rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stiffness", Saxofony_ctrl_reed ); //! stiffness func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stiffness", Saxofony_cget_reed ); //! stiffness if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "aperture", Saxofony_ctrl_aperture ); //! aperture func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "aperture", Saxofony_cget_aperture ); //! aperture if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Saxofony_ctrl_noiseGain ); //! noiseGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noiseGain", Saxofony_cget_noiseGain ); //! noiseGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Saxofony_ctrl_vibratoGain ); //! vibratoGain func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Saxofony_cget_vibratoGain ); //! vibratoGain if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Saxofony_ctrl_vibratoFreq ); //! vibratoFreq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", Saxofony_cget_vibratoFreq ); //! vibratoFreq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "blowPosition", Saxofony_ctrl_blowPosition ); //! blowPosition func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "blowPosition", Saxofony_cget_blowPosition ); //! blowPosition if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Saxofony_ctrl_pressure ); //! pressure func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pressure", Saxofony_cget_pressure ); //! pressure if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Shakers ugen //------------------------------------------------------------------------ //! see \example shake-o-matic.ck if( !type_engine_import_ugen_begin( env, "Shakers", "StkInstrument", env->global(), Shakers_ctor, Shakers_dtor, Shakers_tick, Shakers_pmsg ) ) return FALSE; // member variable // Shakers_offset_data = type_engine_import_mvar ( env, "int", "@Shakers_data", FALSE ); // if( Shakers_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "int", "which", Shakers_ctrl_which ); //! select instrument func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "which", Shakers_cget_which ); //! select instrument if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", Shakers_ctrl_which ); //! select instrument func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "preset", Shakers_cget_which ); //! select instrument if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "energy", Shakers_ctrl_energy ); //! energy func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "energy", Shakers_cget_energy ); //! energy if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "decay", Shakers_ctrl_decay ); //! decay func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "decay", Shakers_cget_decay ); //! decay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "objects", Shakers_ctrl_objects ); //! objects func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "objects", Shakers_cget_objects ); //! objects if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", Shakers_ctrl_freq ); //! frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", Shakers_cget_freq ); //! frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noteOn", Shakers_ctrl_noteOn ); //! note on func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noteOff", Shakers_ctrl_noteOff ); //! note off func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Sitar ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Sitar", "StkInstrument", env->global(), Sitar_ctor, Sitar_dtor, Sitar_tick, Sitar_pmsg ) ) return FALSE; // member variable // Sitar_offset_data = type_engine_import_mvar ( env, "int", "@Sitar_data", FALSE ); // if( Sitar_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "pluck", Sitar_ctrl_pluck ); //! pluck func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "clear", Sitar_ctrl_clear ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin StifKarp ugen //------------------------------------------------------------------------ //! see \example stifkarp.ck if( !type_engine_import_ugen_begin( env, "StifKarp", "StkInstrument", env->global(), StifKarp_ctor, StifKarp_dtor, StifKarp_tick, StifKarp_pmsg ) ) return FALSE; // member variable // StifKarp_offset_data = type_engine_import_mvar ( env, "int", "@StifKarp_data", FALSE ); // if( StifKarp_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "pluck", StifKarp_ctrl_pluck ); //! pluck func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "clear", StifKarp_ctrl_clear ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pickupPosition", StifKarp_ctrl_pickupPosition ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pickupPosition", StifKarp_cget_pickupPosition ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stretch", StifKarp_ctrl_stretch ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "stretch", StifKarp_cget_stretch ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "sustain", StifKarp_ctrl_sustain ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "sustain", StifKarp_cget_sustain ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "baseLoopGain", StifKarp_ctrl_baseLoopGain ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "baseLoopGain", StifKarp_cget_baseLoopGain ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin VoicForm ugen //------------------------------------------------------------------------ //! see \example voic-o-form.ck if( !type_engine_import_ugen_begin( env, "VoicForm", "StkInstrument", env->global(), VoicForm_ctor, VoicForm_dtor, VoicForm_tick, VoicForm_pmsg ) ) return FALSE; // member variable // VoicForm_offset_data = type_engine_import_mvar ( env, "int", "@VoicForm_data", FALSE ); // if( VoicForm_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "string", "phoneme", VoicForm_ctrl_phoneme ); //! select phoneme ( above ) func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "phoneme", VoicForm_cget_phoneme ); //! select phoneme ( above ) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "speak", VoicForm_ctrl_speak ); //! start singing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "quiet", VoicForm_ctrl_quiet ); //! stop singing func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "voiced", VoicForm_ctrl_voiced ); //! set mix for voiced component func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "voiced", VoicForm_cget_voiced ); //! set mix for voiced component if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "unVoiced", VoicForm_ctrl_unVoiced ); //! set mix for unvoiced component func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "unVoiced", VoicForm_cget_unVoiced ); //! set mix for unvoiced component if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pitchSweepRate", VoicForm_ctrl_pitchSweepRate ); //! pitch sweep func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pitchSweepRate", VoicForm_cget_pitchSweepRate ); //! pitch sweep if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "voiceMix", VoicForm_ctrl_voiceMix ); //! voiced/unvoiced mix func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "voiceMix", VoicForm_cget_voiceMix ); //! voiced/unvoiced mix if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "phonemeNum", VoicForm_ctrl_selPhoneme ); //! select phoneme by number func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "phonemeNum", VoicForm_cget_selPhoneme ); //! select phoneme by number if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", VoicForm_ctrl_vibratoFreq );//! vibrato func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoFreq", VoicForm_cget_vibratoFreq );//! vibrato if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", VoicForm_ctrl_vibratoGain );//! vibrato depth func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", VoicForm_cget_vibratoGain );//! vibrato depth if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "loudness", VoicForm_ctrl_loudness ); //! 'loudness' of voicee func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "loudness", VoicForm_cget_loudness ); //! 'loudness' of voicee if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //! \section2 stk - fm synths //------------------------------------------------------------------------ // begin FM ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "FM", "StkInstrument", env->global(), FM_ctor, FM_dtor, FM_tick, FM_pmsg ) ) return FALSE; // member variable // all subclasses of FM must use this offset, as this is where the inherited // functions will look for the object // the other option would be to keep SubClass_offset_data, but assign // the value to FM_offset_data. // FM_offset_data = type_engine_import_mvar ( env, "int", "@FM_data", FALSE ); // if( FM_offset_data == CK_INVALID_OFFSET ) goto error; FM_offset_data = Instrmnt_offset_data; func = make_new_mfun( "float", "lfoDepth", FM_ctrl_modDepth ); //!modulation Depth func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoDepth", FM_cget_modDepth ); //!modulation Depth if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoSpeed", FM_ctrl_modSpeed ); //!modulation Speed func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "lfoSpeed", FM_cget_modSpeed ); //!modulation Speed if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "afterTouch", FM_ctrl_afterTouch ); //!aftertouch func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "afterTouch", FM_cget_afterTouch ); //!aftertouch if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "controlOne", FM_ctrl_control1 ); //! FM control 1 func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "controlOne", FM_cget_control1 ); //! FM control 1 if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "controlTwo", FM_ctrl_control2 ); //! FM control 2 func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "controlTwo", FM_cget_control2 ); //! FM control 2 if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BeeThree ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BeeThree", "FM", env->global(), BeeThree_ctor, BeeThree_dtor, BeeThree_tick, BeeThree_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin FMVoices ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "FMVoices", "FM", env->global(), FMVoices_ctor, FMVoices_dtor, FMVoices_tick, FMVoices_pmsg ) ) return FALSE; func = make_new_mfun( "float", "vowel", FMVoices_ctrl_vowel ); //!select vowel func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vowel", FMVoices_cget_vowel ); //!select vowel if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "spectralTilt", FMVoices_ctrl_spectralTilt ); //! spectral tilt func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "spectralTilt", FMVoices_cget_spectralTilt ); //! spectral tilt if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "adsrTarget", FMVoices_ctrl_adsrTarget ); //!adsr targets func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "adsrTarget", FMVoices_cget_adsrTarget ); //!adsr targets if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin HevyMetl ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "HevyMetl", "FM", env->global(), HevyMetl_ctor, HevyMetl_dtor, HevyMetl_tick, HevyMetl_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin PercFlut ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "PercFlut", "FM", env->global(), PercFlut_ctor, PercFlut_dtor, PercFlut_tick, PercFlut_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Rhodey ugen //------------------------------------------------------------------------ //! see \examples rhodey.ck if( !type_engine_import_ugen_begin( env, "Rhodey", "FM", env->global(), Rhodey_ctor, Rhodey_dtor, Rhodey_tick, Rhodey_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin TubeBell ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "TubeBell", "FM", env->global(), TubeBell_ctor, TubeBell_dtor, TubeBell_tick, TubeBell_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Wurley ugen //------------------------------------------------------------------------ //! see \examples wurley.ck if( !type_engine_import_ugen_begin( env, "Wurley", "FM", env->global(), Wurley_ctor, Wurley_dtor, Wurley_tick, Wurley_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //end FM //! \section stk - delay //------------------------------------------------------------------------ // begin Delay ugen //------------------------------------------------------------------------ //! see \example net_relay.ck if( !type_engine_import_ugen_begin( env, "Delay", "UGen", env->global(), Delay_ctor, Delay_dtor, Delay_tick, Delay_pmsg ) ) return FALSE; //member variable Delay_offset_data = type_engine_import_mvar ( env, "int", "@Delay_data", FALSE ); if( Delay_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "dur", "delay", Delay_ctrl_delay ); //! length of delay func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "delay", Delay_cget_delay ); //! length of delay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", Delay_ctrl_max ); //! max delay (buffer size) func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", Delay_cget_max ); //! max delay (buffer size) if( !type_engine_import_mfun( env, func ) ) goto error; // delay 'subs' not actually extending . // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin DelayA ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "DelayA", "UGen", env->global(), DelayA_ctor, DelayA_dtor, DelayA_tick, DelayA_pmsg ) ) return FALSE; //member variable DelayA_offset_data = type_engine_import_mvar ( env, "int", "@DelayA_data", FALSE ); if( DelayA_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "dur", "delay", DelayA_ctrl_delay ); //! length of delay func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "delay", DelayA_cget_delay ); //! length of delay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", DelayA_ctrl_max ); //! max delay ( buffer size ) func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", DelayA_cget_max ); //! max delay ( buffer size ) if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin DelayL ugen //------------------------------------------------------------------------ //! see \example i-robot.ck if( !type_engine_import_ugen_begin( env, "DelayL", "UGen", env->global(), DelayL_ctor, DelayL_dtor, DelayL_tick, DelayL_pmsg ) ) return FALSE; //member variable DelayL_offset_data = type_engine_import_mvar ( env, "int", "@DelayL_data", FALSE ); if( DelayL_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "dur", "delay", DelayL_ctrl_delay ); //! length of delay func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "delay", DelayL_cget_delay ); //! length of delay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", DelayL_ctrl_max ); //! max delay ( buffer size ) func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", DelayL_cget_max ); //! max delay ( buffer size ) if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Echo ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Echo", "UGen", env->global(), Echo_ctor, Echo_dtor, Echo_tick, Echo_pmsg ) ) return FALSE; //member variable Echo_offset_data = type_engine_import_mvar ( env, "int", "@Echo_data", FALSE ); if( Echo_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "dur", "delay", Echo_ctrl_delay ); //! length of echo func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "delay", Echo_cget_delay ); //! length of echo if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", Echo_ctrl_max ); //! max delay func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "max", Echo_cget_max ); //! max delay if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", Echo_ctrl_mix ); //! mix level ( wet/dry ) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", Echo_cget_mix ); //! mix level ( wet/dry ) if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //! \section stk - envelopes //------------------------------------------------------------------------ // begin Envelope ugen //------------------------------------------------------------------------ //! see \example sixty.ck if( !type_engine_import_ugen_begin( env, "Envelope", "UGen", env->global(), Envelope_ctor, Envelope_dtor, Envelope_tick, Envelope_pmsg ) ) return FALSE; //member variable Envelope_offset_data = type_engine_import_mvar ( env, "int", "@Envelope_data", FALSE ); if( Envelope_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "int", "keyOn", Envelope_ctrl_keyOn0 ); //! ramp to 1.0 if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "keyOn", Envelope_ctrl_keyOn ); //! ramp to 1.0 func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "keyOff", Envelope_ctrl_keyOff0 ); //! ramp to 0.0 if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "keyOff", Envelope_ctrl_keyOff ); //! ramp to 0.0 func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "target", Envelope_ctrl_target ); //! ramp to arbitrary value. func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "target", Envelope_cget_target ); //! ramp to arbitrary value. if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "time", Envelope_ctrl_time ); //! time to reach target func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "time", Envelope_cget_time ); //! time to reach target if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "duration", Envelope_ctrl_duration ); //! time to reach target func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "duration", Envelope_cget_duration ); //! time to reach target if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Envelope_ctrl_rate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", Envelope_cget_rate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "value", Envelope_ctrl_value ); //! set immediate value func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "value", Envelope_cget_value ); //! set immediate value if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin ADSR ugen //------------------------------------------------------------------------ //! see \example adsr.ck if( !type_engine_import_ugen_begin( env, "ADSR", "Envelope", env->global(), ADSR_ctor, ADSR_dtor, ADSR_tick, ADSR_pmsg ) ) return FALSE; func = make_new_mfun( "dur", "attackTime", ADSR_ctrl_attackTime ); //! attack time func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "attackTime", ADSR_cget_attackTime ); //! attack time if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "attackRate", ADSR_ctrl_attackRate ); //! attack rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "attackRate", ADSR_cget_attackRate ); //! attack rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "decayTime", ADSR_ctrl_decayTime ); //! decay time func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "decayTime", ADSR_cget_decayTime ); //! decay time if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "decayRate", ADSR_ctrl_decayRate ); //! decay rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "decayRate", ADSR_cget_decayRate ); //! decay rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "sustainLevel", ADSR_ctrl_sustainLevel ); //! sustain level func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "sustainLevel", ADSR_cget_sustainLevel ); //! sustain level if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "releaseTime", ADSR_ctrl_releaseTime ); //! release time func->add_arg( "dur", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "releaseTime", ADSR_cget_releaseTime ); //! release time if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "releaseRate", ADSR_ctrl_releaseRate ); //! release rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "releaseRate", ADSR_cget_releaseRate ); //! release rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "set", ADSR_ctrl_set ); //! set func->add_arg( "float", "attackTime" ); func->add_arg( "float", "decayTime" ); func->add_arg( "float", "sustainLevel" ); func->add_arg( "float", "releaseTime" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "set", ADSR_ctrl_set2 ); //! set func->add_arg( "dur", "attackDuration" ); func->add_arg( "dur", "decayDuration" ); func->add_arg( "float", "sustainLevel" ); func->add_arg( "dur", "releaseDuration" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "state", ADSR_cget_state ); //! attack=0, decay=1 , sustain=2, release=3, done=4 if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //uhhh we are supposed to have target and value here as well.. d'oh //! \section stk - filters /* -- using native BiQuad -- //------------------------------------------------------------------------ // begin BiQuad ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BiQuadStk", "UGen", env->global(), BiQuad_ctor, BiQuad_tick, BiQuad_pmsg ) ) return FALSE; //member variable BiQuad_offset_data = type_engine_import_mvar ( env, "int", "@BiQuad_data", FALSE ); if( BiQuad_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "b2", BiQuad_ctrl_b2 ); //! b2 coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b2", BiQuad_cget_b2 ); //! b2 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", BiQuad_ctrl_b1 ); //! b1 coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", BiQuad_cget_b1 ); //! b1 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", BiQuad_ctrl_b0 ); //! b0 coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", BiQuad_cget_b0 ); //! b0 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a2", BiQuad_ctrl_a2 ); //! a2 coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a2", BiQuad_cget_a2 ); //! a2 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a1", BiQuad_ctrl_a1 ); //! a1 coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a1", BiQuad_cget_a1 ); //! a1 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a0", BiQuad_cget_a0 ); //! a0 coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pfreq", BiQuad_ctrl_pfreq ); //! set resonance frequency (poles) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pfreq", BiQuad_cget_pfreq ); //! get resonance frequency (poles) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "prad", BiQuad_ctrl_prad ); //! pole radius (less than 1 to be stable) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "prad", BiQuad_cget_prad ); //! pole radius (less than 1 to be stable) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "zfreq", BiQuad_ctrl_zfreq ); //! notch frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "zfreq", BiQuad_cget_zfreq ); //! notch frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "zrad", BiQuad_ctrl_zrad ); //! zero radius func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "zrad", BiQuad_cget_zrad ); //! zero radius if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "norm", BiQuad_ctrl_norm ); //! normalization func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "eqzs", BiQuad_ctrl_eqzs ); //! equal gain zeroes func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); */ //------------------------------------------------------------------------ // begin FilterStk ugen (orginally Filter) //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "FilterStk", "UGen", env->global(), FilterStk_ctor, FilterStk_dtor, FilterStk_tick, FilterStk_pmsg ) ) return FALSE; // member variable FilterStk_offset_data = type_engine_import_mvar ( env, "int", "@FilterStk_data", FALSE ); if( FilterStk_offset_data == CK_INVALID_OFFSET ) goto error; // coefs func = make_new_mfun( "string", "coefs", FilterStk_ctrl_coefs ); func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin OnePole ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "OnePole", "UGen", env->global(), OnePole_ctor, OnePole_dtor, OnePole_tick, OnePole_pmsg ) ) return FALSE; // member variable OnePole_offset_data = type_engine_import_mvar ( env, "int", "@OnePole_data", FALSE ); if( OnePole_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "a1", OnePole_ctrl_a1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a1", OnePole_cget_a1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", OnePole_ctrl_b0 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", OnePole_cget_b0 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pole", OnePole_ctrl_pole ); //! set pole position along real axis of z-plane func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pole", OnePole_cget_pole ); //! set pole position along real axis of z-plane if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin TwoPole ugen //------------------------------------------------------------------------ //! see \example powerup.ck if( !type_engine_import_ugen_begin( env, "TwoPole", "UGen", env->global(), TwoPole_ctor, TwoPole_dtor, TwoPole_tick, TwoPole_pmsg ) ) return FALSE; //member variable TwoPole_offset_data = type_engine_import_mvar ( env, "int", "@TwoPole_data", FALSE ); if( TwoPole_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "a1", TwoPole_ctrl_a1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a1", TwoPole_cget_a1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a2", TwoPole_ctrl_a2 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a2", TwoPole_cget_a2 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", TwoPole_ctrl_b0 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", TwoPole_cget_b0 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", TwoPole_ctrl_freq ); //! filter resonance frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", TwoPole_cget_freq ); //! filter resonance frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "radius", TwoPole_ctrl_radius ); //! filter resonance radius func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "radius", TwoPole_cget_radius ); //! filter resonance radius if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "norm", TwoPole_ctrl_norm ); //! toggle filter normalization func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "norm", TwoPole_cget_norm ); //! toggle filter normalization if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin OneZero ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "OneZero", "UGen", env->global(), OneZero_ctor, OneZero_dtor, OneZero_tick, OneZero_pmsg ) ) return FALSE; //member variable OneZero_offset_data = type_engine_import_mvar ( env, "int", "@OneZero_data", FALSE ); if( OneZero_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "zero", OneZero_ctrl_zero ); //! set zero position func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "zero", OneZero_cget_zero ); //! set zero position if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", OneZero_ctrl_b0 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", OneZero_cget_b0 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", OneZero_ctrl_b1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", OneZero_cget_b1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin TwoZero ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "TwoZero", "UGen", env->global(), TwoZero_ctor, TwoZero_dtor, TwoZero_tick, TwoZero_pmsg ) ) return FALSE; //member variable TwoZero_offset_data = type_engine_import_mvar ( env, "int", "@TwoZero_data", FALSE ); if( TwoZero_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "b0", TwoZero_ctrl_b0 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", TwoZero_cget_b0 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", TwoZero_ctrl_b1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", TwoZero_cget_b1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b2", TwoZero_ctrl_b2 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b2", TwoZero_cget_b2 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", TwoZero_ctrl_freq ); //! filter notch frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", TwoZero_cget_freq ); //! filter notch frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "radius", TwoZero_ctrl_radius ); //! filter notch radius func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "radius", TwoZero_cget_radius ); //! filter notch radius if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin PoleZero ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "PoleZero", "UGen", env->global(), PoleZero_ctor, PoleZero_dtor, PoleZero_tick, PoleZero_pmsg ) ) return FALSE; //member variable PoleZero_offset_data = type_engine_import_mvar ( env, "int", "@PoleZero_data", FALSE ); if( PoleZero_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "a1", PoleZero_ctrl_a1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "a1", PoleZero_cget_a1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", PoleZero_ctrl_b0 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b0", PoleZero_cget_b0 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", PoleZero_ctrl_b1 ); //! filter coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "b1", PoleZero_cget_b1 ); //! filter coefficient if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "blockZero", PoleZero_ctrl_blockZero ); //! DC blocking filter with given pole position func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "blockZero", PoleZero_cget_blockZero ); //! DC blocking filter with given pole position if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "allpass", PoleZero_ctrl_allpass ); //!allpass filter with given coefficient func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "allpass", PoleZero_cget_allpass ); //!allpass filter with given coefficient if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //end Filters //! \section stk-reverbs //------------------------------------------------------------------------ // begin JCRev ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "JCRev", "UGen", env->global(), JCRev_ctor, JCRev_dtor, JCRev_tick, JCRev_pmsg ) ) return FALSE; //member variable JCRev_offset_data = type_engine_import_mvar ( env, "int", "@JCRev_data", FALSE ); if( JCRev_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "mix", JCRev_ctrl_mix ); //! mix level func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", JCRev_cget_mix ); //! mix level if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin NRev ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "NRev", "UGen", env->global(), NRev_ctor, NRev_dtor, NRev_tick, NRev_pmsg ) ) return FALSE; //member variable NRev_offset_data = type_engine_import_mvar ( env, "int", "@NRev_data", FALSE ); if( NRev_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "mix", NRev_ctrl_mix ); // set effect mix func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", NRev_cget_mix ); // set effect mix if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin PRCRev ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "PRCRev", "UGen", env->global(), PRCRev_ctor, PRCRev_dtor, PRCRev_tick, PRCRev_pmsg ) ) return FALSE; //member variable PRCRev_offset_data = type_engine_import_mvar ( env, "int", "@PRCRev_data", FALSE ); if( PRCRev_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "mix", PRCRev_ctrl_mix ); //! mix level func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", PRCRev_cget_mix ); //! mix level if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //! \section components //------------------------------------------------------------------------ // begin Chorus ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Chorus", "UGen", env->global(), Chorus_ctor, Chorus_dtor, Chorus_tick, Chorus_pmsg ) ) return FALSE; //member variable Chorus_offset_data = type_engine_import_mvar ( env, "int", "@Chorus_data", FALSE ); if( Chorus_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "modFreq", Chorus_ctrl_modFreq ); //! modulation frequency func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modFreq", Chorus_cget_modFreq ); //! modulation frequency if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modDepth", Chorus_ctrl_modDepth ); //! modulation depth func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "modDepth", Chorus_cget_modDepth ); //! modulation depth if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", Chorus_ctrl_mix ); //! effect mix func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", Chorus_cget_mix ); //! effect mix if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Modulate ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Modulate", "UGen", env->global(), Modulate_ctor, Modulate_dtor, Modulate_tick, Modulate_pmsg ) ) return FALSE; //member variable Modulate_offset_data = type_engine_import_mvar ( env, "int", "@Modulate_data", FALSE ); if( Modulate_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "vibratoRate", Modulate_ctrl_vibratoRate ); //! set rate of vibrato func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoRate", Modulate_cget_vibratoRate ); //! set rate of vibrato if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Modulate_ctrl_vibratoGain ); //! gain for vibrato func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "vibratoGain", Modulate_cget_vibratoGain ); //! gain for vibrato if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "randomGain", Modulate_ctrl_randomGain ); //! gain for random contribution func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "randomGain", Modulate_cget_randomGain ); //! gain for random contribution if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin PitShift ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "PitShift", "UGen", env->global(), PitShift_ctor, PitShift_dtor, PitShift_tick, PitShift_pmsg ) ) return FALSE; //member variable PitShift_offset_data = type_engine_import_mvar ( env, "int", "@PitShift_data", FALSE ); if( PitShift_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "shift", PitShift_ctrl_shift ); //! degree of pitch shifting func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "shift", PitShift_cget_shift ); //! degree of pitch shifting if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", PitShift_ctrl_effectMix ); //! mix level func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "mix", PitShift_cget_effectMix ); //! mix level if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "effectMix", PitShift_ctrl_effectMix ); //! mix level func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "effectMix", PitShift_cget_effectMix ); //! mix level if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin SubNoise ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "SubNoise", "UGen", env->global(), SubNoise_ctor, SubNoise_dtor, SubNoise_tick, SubNoise_pmsg ) ) return FALSE; //member variable SubNoise_offset_data = type_engine_import_mvar ( env, "int", "@SubNoise_data", FALSE ); if( SubNoise_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "int", "rate", SubNoise_ctrl_rate ); //! subsampling rate func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "rate", SubNoise_cget_rate ); //! subsampling rate if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //! \section stk - file i/o //------------------------------------------------------------------------ // begin WvIn ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "WvIn", "UGen", env->global(), WvIn_ctor, WvIn_dtor, WvIn_tick, WvIn_pmsg ) ) return FALSE; //member variable WvIn_offset_data = type_engine_import_mvar ( env, "int", "@WvIn_data", FALSE ); if( WvIn_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "rate", WvIn_ctrl_rate ); //! playback rate func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", WvIn_cget_rate ); //! playback rate if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "path", WvIn_ctrl_path ); //! specifies file to be played func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "path", WvIn_cget_path ); //! specifies file to be played if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin WaveLoop ugen //------------------------------------------------------------------------ //! see \example dope.ck if( !type_engine_import_ugen_begin( env, "WaveLoop", "WvIn", env->global(), WaveLoop_ctor, WaveLoop_dtor, WaveLoop_tick, WaveLoop_pmsg ) ) return FALSE; func = make_new_mfun( "float", "freq", WaveLoop_ctrl_freq ); //! set frequency of playback ( loops / second ) func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", WaveLoop_cget_freq ); //! set frequency of playback ( loops / second ) if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "addPhase", WaveLoop_ctrl_phase ); //! offset by phase func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "addPhase", WaveLoop_cget_phase ); //! offset by phase if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "addPhaseOffset", WaveLoop_ctrl_phaseOffset ); //! set phase offset func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "addPhaseOffset", WaveLoop_cget_phaseOffset ); //! set phase offset if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin WvOut ugen //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "WvOut", "UGen", env->global(), WvOut_ctor, WvOut_dtor, WvOut_tick, WvOut_pmsg ) ) return FALSE; //member variable WvOut_offset_data = type_engine_import_mvar ( env, "int", "@WvOut_data", FALSE ); if( WvOut_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "string", "matFilename", WvOut_ctrl_matFilename ); //!open matlab file for writing func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "sndFilename", WvOut_ctrl_sndFilename ); //!open snd file for writing func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "wavFilename", WvOut_ctrl_wavFilename ); //!open WAVE file for writing func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "rawFilename", WvOut_ctrl_rawFilename ); //!open raw file for writing func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "aifFilename", WvOut_ctrl_aifFilename ); //!open AIFF file for writing func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "filename", WvOut_cget_filename ); //!get filename if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "record", WvOut_ctrl_record ); // !start/stop output func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "record", WvOut_cget_record ); // !start/stop output if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "closeFile", WvOut_ctrl_closeFile ); //! close file properly func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "closeFile", WvOut_ctrl_closeFile ); //! close file properly if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "autoPrefix", WvOut_ctrl_autoPrefix ); //! set/get auto prefix string func->add_arg( "string", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "string", "autoPrefix", WvOut_cget_autoPrefix ); //! set/get auto prefix string if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BLT (BandLtd) //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BLT", "UGen", env->global(), BLT_ctor, BLT_dtor, BLT_tick, BLT_pmsg ) ) return FALSE; // member variable // all subclasses of BLT must use this offset, as this is where the // inherited functions will look for the object // the other option would be to keep SubClass_offset_data, but assign // the value to BLT_offset_data. BLT_offset_data = type_engine_import_mvar( env, "int", "@BLT_data", FALSE ); if( BLT_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "float", "phase", BLT_ctrl_phase ); //!set phase func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "phase", BLT_cget_phase ); //!get phase if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", BLT_ctrl_freq ); //!set freq func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "freq", BLT_cget_freq ); //!get freq if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "harmonics", BLT_ctrl_harmonics ); //!set harmonics func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "harmonics", BLT_cget_harmonics ); //!get harmonics if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin Blit //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "Blit", "BLT", env->global(), Blit_ctor, Blit_dtor, Blit_tick, Blit_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BlitSaw //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BlitSaw", "BLT", env->global(), BlitSaw_ctor, BlitSaw_dtor, BlitSaw_tick, BlitSaw_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin BlitSquare //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "BlitSquare", "BLT", env->global(), BlitSquare_ctor, BlitSquare_dtor, BlitSquare_tick, BlitSquare_pmsg ) ) return FALSE; // end the class import type_engine_import_class_end( env ); //------------------------------------------------------------------------ // begin JetTable //------------------------------------------------------------------------ if( !type_engine_import_ugen_begin( env, "JetTabl", "UGen", env->global(), JetTabl_ctor, JetTabl_dtor, JetTabl_tick, JetTabl_pmsg ) ) return FALSE; // member variable JetTabl_offset_data = type_engine_import_mvar( env, "int", "@JetTabl_data", FALSE ); if( JetTabl_offset_data == CK_INVALID_OFFSET ) goto error; // end the class import type_engine_import_class_end( env ); // Mesh2D if( !type_engine_import_ugen_begin( env, "Mesh2D", "UGen", env->global(), Mesh2D_ctor, Mesh2D_dtor, Mesh2D_tick, Mesh2D_pmsg ) ) return FALSE; //member variable Mesh2D_offset_data = type_engine_import_mvar ( env, "int", "@Mesh2D_data", FALSE ); if( Mesh2D_offset_data == CK_INVALID_OFFSET ) goto error; func = make_new_mfun( "int", "nx", Mesh2D_ctrl_nx ); //! nx func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "nx", Mesh2D_cget_nx ); //! nx if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "ny", Mesh2D_ctrl_ny ); //! nx func->add_arg( "int", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "ny", Mesh2D_cget_ny ); //! nx if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "inputPosition", Mesh2D_ctrl_input_position ); //! nx func->add_arg( "float", "xval" ); func->add_arg( "float", "yval" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "decay", Mesh2D_ctrl_decay ); //! nx func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "energy", Mesh2D_cget_energy ); //! nx if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noteOn", Mesh2D_ctrl_note_on ); //! start func->add_arg( "float", "note" ); func->add_arg( "float", "vel" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "noteOff", Mesh2D_ctrl_note_off ); //! stop func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "controlChange", Mesh2D_ctrl_control_change ); //! select instrument func->add_arg( "int", "ctrl" ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; //error recovery - end class and throw flag... error: // end the class import type_engine_import_class_end( env ); return FALSE; } struct SKINISpec { char messageString[32]; long type; long data2; long data3; }; /* SEE COMMENT BLOCK AT BOTTOM FOR FIELDS AND USES */ /* MessageString ,type, ch?, data2 , data3 */ struct SKINISpec skini_msgs[__SK_MaxMsgTypes_] = { {"NoteOff" , __SK_NoteOff_, SK_DBL, SK_DBL}, {"NoteOn" , __SK_NoteOn_, SK_DBL, SK_DBL}, {"PolyPressure" , __SK_PolyPressure_, SK_DBL, SK_DBL}, {"ControlChange" , __SK_ControlChange_, SK_INT, SK_DBL}, {"ProgramChange" , __SK_ProgramChange_, SK_DBL, SK_DBL}, {"AfterTouch" , __SK_AfterTouch_, SK_DBL, NOPE}, {"ChannelPressure" ,__SK_ChannelPressure_, SK_DBL, NOPE}, {"PitchWheel" , __SK_PitchWheel_, SK_DBL, NOPE}, {"PitchBend" , __SK_PitchBend_, SK_DBL, NOPE}, {"PitchChange" , __SK_PitchChange_, SK_DBL, NOPE}, {"Clock" , __SK_Clock_, NOPE, NOPE}, {"Undefined" , 249, NOPE, NOPE}, {"SongStart" , __SK_SongStart_, NOPE, NOPE}, {"Continue" , __SK_Continue_, NOPE, NOPE}, {"SongStop" , __SK_SongStop_, NOPE, NOPE}, {"Undefined" , 253, NOPE, NOPE}, {"ActiveSensing" , __SK_ActiveSensing_, NOPE, NOPE}, {"SystemReset" , __SK_SystemReset_, NOPE, NOPE}, {"Volume" , __SK_ControlChange_, __SK_Volume_ , SK_DBL}, {"ModWheel" , __SK_ControlChange_, __SK_ModWheel_ , SK_DBL}, {"Modulation" , __SK_ControlChange_, __SK_Modulation_ , SK_DBL}, {"Breath" , __SK_ControlChange_, __SK_Breath_ , SK_DBL}, {"FootControl" , __SK_ControlChange_, __SK_FootControl_ , SK_DBL}, {"Portamento" , __SK_ControlChange_, __SK_Portamento_ , SK_DBL}, {"Balance" , __SK_ControlChange_, __SK_Balance_ , SK_DBL}, {"Pan" , __SK_ControlChange_, __SK_Pan_ , SK_DBL}, {"Sustain" , __SK_ControlChange_, __SK_Sustain_ , SK_DBL}, {"Damper" , __SK_ControlChange_, __SK_Damper_ , SK_DBL}, {"Expression" , __SK_ControlChange_, __SK_Expression_ , SK_DBL}, {"NoiseLevel" , __SK_ControlChange_, __SK_NoiseLevel_ , SK_DBL}, {"PickPosition" , __SK_ControlChange_, __SK_PickPosition_ , SK_DBL}, {"StringDamping" , __SK_ControlChange_, __SK_StringDamping_ , SK_DBL}, {"StringDetune" , __SK_ControlChange_, __SK_StringDetune_ , SK_DBL}, {"BodySize" , __SK_ControlChange_, __SK_BodySize_ , SK_DBL}, {"BowPressure" , __SK_ControlChange_, __SK_BowPressure_ , SK_DBL}, {"BowPosition" , __SK_ControlChange_, __SK_BowPosition_ , SK_DBL}, {"BowBeta" , __SK_ControlChange_, __SK_BowBeta_ , SK_DBL}, {"ReedStiffness" , __SK_ControlChange_, __SK_ReedStiffness_ , SK_DBL}, {"ReedRestPos" , __SK_ControlChange_, __SK_ReedRestPos_ , SK_DBL}, {"FluteEmbouchure" , __SK_ControlChange_, __SK_FluteEmbouchure_, SK_DBL}, {"LipTension" , __SK_ControlChange_, __SK_LipTension_ , SK_DBL}, {"StrikePosition" , __SK_ControlChange_, __SK_StrikePosition_, SK_DBL}, {"StickHardness" , __SK_ControlChange_, __SK_StickHardness_ , SK_DBL}, {"TrillDepth" , __SK_ControlChange_, __SK_TrillDepth_ , SK_DBL}, {"TrillSpeed" , __SK_ControlChange_, __SK_TrillSpeed_ , SK_DBL}, {"Strumming" , __SK_ControlChange_, __SK_Strumming_ , 127 }, {"NotStrumming" , __SK_ControlChange_, __SK_Strumming_ , 0 }, {"PlayerSkill" , __SK_ControlChange_, __SK_PlayerSkill_ , SK_DBL}, {"Chord" , __SK_Chord_ , SK_DBL , SK_STR }, {"ChordOff" , __SK_ChordOff_ , SK_DBL , NOPE }, {"ShakerInst" , __SK_ControlChange_, __SK_ShakerInst_ , SK_DBL}, {"Maraca" , __SK_ControlChange_, __SK_ShakerInst_ , 0 }, {"Sekere" , __SK_ControlChange_, __SK_ShakerInst_ , 1 }, {"Cabasa" , __SK_ControlChange_, __SK_ShakerInst_ , 2 }, {"Bamboo" , __SK_ControlChange_, __SK_ShakerInst_ , 3 }, {"Waterdrp" , __SK_ControlChange_, __SK_ShakerInst_ , 4 }, {"Tambourn" , __SK_ControlChange_, __SK_ShakerInst_ , 5 }, {"Sleighbl" , __SK_ControlChange_, __SK_ShakerInst_ , 6 }, {"Guiro" , __SK_ControlChange_, __SK_ShakerInst_ , 7 }, {"OpenFile" , 256, SK_STR , NOPE}, {"SetPath" , 257, SK_STR , NOPE}, {"FilePath" , __SK_SINGER_FilePath_, SK_STR , NOPE}, {"Frequency" , __SK_SINGER_Frequency_, SK_STR , NOPE}, {"NoteName" , __SK_SINGER_NoteName_, SK_STR , NOPE}, {"VocalShape" , __SK_SINGER_Shape_ , SK_STR , NOPE}, {"Glottis" , __SK_SINGER_Glot_ , SK_STR , NOPE}, {"VoicedUnVoiced" , __SK_SINGER_VoicedUnVoiced_, SK_DBL , SK_STR}, {"Synthesize" , __SK_SINGER_Synthesize_, SK_STR , NOPE}, {"Silence" , __SK_SINGER_Silence_, SK_STR , NOPE}, {"VibratoAmt" , __SK_ControlChange_ ,__SK_SINGER_VibratoAmt_,SK_DBL}, {"RndVibAmt" , __SK_SINGER_RndVibAmt_ ,SK_STR, NOPE}, {"VibFreq" , __SK_ControlChange_ ,__SK_SINGER_VibFreq_ ,SK_DBL} }; /** FORMAT: *************************************************************/ /* */ /* MessageStr$ ,type, data2, data3, */ /* */ /* type is the message type sent back from the SKINI line parser. */ /* data is either */ /* NOPE : field not used, specifically, there aren't going */ /* to be any more fields on this line. So if there */ /* is is NOPE in data2, data3 won't even be checked */ /* SK_INT : byte (actually scanned as 32 bit signed integer) */ /* If it's a MIDI data field which is required to */ /* be an integer, like a controller number, it's */ /* 0-127. Otherwise) get creative with SK_INTs */ /* SK_DBL : double precision floating point. SKINI uses these */ /* in the MIDI context for note numbers with micro */ /* tuning, velocities, controller values, etc. */ /* SK_STR : only valid in final field. This allows (nearly) */ /* arbitrary message types to be supported by simply */ /* scanning the string to EndOfLine and then passing */ /* it to a more intellegent handler. For example, */ /* MIDI SYSEX (system exclusive) messages of up to */ /* 256bytes can be read as space-delimited integers */ /* into the 1K SK_STR buffer. Longer bulk dumps, */ /* soundfiles, etc. should be handled as a new */ /* message type pointing to a FileName stored in the */ /* SK_STR field, or as a new type of multi-line */ /* message. */ /* */ /*************************************************************************/ /***************************************************/ /*! \class ADSR \brief STK ADSR envelope class. This Envelope subclass implements a traditional ADSR (Attack, Decay, Sustain, Release) envelope. It responds to simple keyOn and keyOff messages, keeping track of its state. The \e state = ADSR::DONE after the envelope value reaches 0.0 in the ADSR::RELEASE state. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include "ugen_stk.h" ADSR :: ADSR() : Envelope() { target = (MY_FLOAT) 0.0; value = (MY_FLOAT) 0.0; attackRate = (MY_FLOAT) 0.001; decayRate = (MY_FLOAT) 0.001; sustainLevel = (MY_FLOAT) 0.5; releaseRate = (MY_FLOAT) 0.01; m_decayTime = (MY_FLOAT) -1.0; // not used m_releaseTime = (MY_FLOAT) -1.0; // not used state = ATTACK; } ADSR :: ~ADSR() { } void ADSR :: keyOn() { target = (MY_FLOAT) 1.0; rate = attackRate; state = ATTACK; } void ADSR :: keyOff() { // chuck if( m_releaseTime > 0 ) { // in case release triggered before sustain rate = value / (m_releaseTime * Stk::sampleRate()); } else { // rate was set rate = releaseRate; } target = (MY_FLOAT) 0.0; state = RELEASE; } void ADSR :: setAttackRate(MY_FLOAT aRate) { if (aRate < 0.0) { printf("[chuck](via ADSR): negative rates not allowed ... correcting!\n"); attackRate = -aRate; } else attackRate = aRate; } void ADSR :: setDecayRate(MY_FLOAT aRate) { if (aRate < 0.0) { printf("[chuck](via ADSR): negative rates not allowed ... correcting!\n"); decayRate = -aRate; } else decayRate = aRate; // chuck m_decayTime = -1.0; } void ADSR :: setSustainLevel(MY_FLOAT aLevel) { if (aLevel < 0.0 ) { printf("[chuck](via ADSR): sustain level out of range ... correcting!\n"); sustainLevel = (MY_FLOAT) 0.0; } else sustainLevel = aLevel; // chuck: need to recompute decay and release rates if( m_decayTime > 0.0 ) setDecayTime( m_decayTime ); if( m_releaseTime > 0.0 ) setReleaseTime( m_releaseTime ); } void ADSR :: setReleaseRate(MY_FLOAT aRate) { if (aRate < 0.0) { printf("[chuck](via ADSR): negative rates not allowed ... correcting!\n"); releaseRate = -aRate; } else releaseRate = aRate; // chuck m_releaseTime = -1.0; } void ADSR :: setAttackTime(MY_FLOAT aTime) { if (aTime < 0.0) { printf("[chuck](via ADSR): negative rates not allowed ... correcting!\n"); attackRate = 1.0 / ( -aTime * Stk::sampleRate() ); } else attackRate = 1.0 / ( aTime * Stk::sampleRate() ); } void ADSR :: setDecayTime(MY_FLOAT aTime) { if (aTime < 0.0) { printf("[chuck](via ADSR): negative times not allowed ... correcting!\n"); // chuck: compute rate for 1.0 to sustain decayRate = (1.0 - sustainLevel) / ( -aTime * Stk::sampleRate() ); } else if( aTime == 0.0 ) { // printf("[chuck](via ADSR): zero decay time not allowed ... correcting!\n"); decayRate = FLT_MAX; // a big number } else decayRate = (1.0 - sustainLevel) / ( aTime * Stk::sampleRate() ); // chuck m_decayTime = aTime; } void ADSR :: setReleaseTime(MY_FLOAT aTime) { if (aTime < 0.0) { printf("[chuck](via ADSR): negative times not allowed ... correcting!\n"); releaseRate = sustainLevel / ( -aTime * Stk::sampleRate() ); } else releaseRate = sustainLevel / ( aTime * Stk::sampleRate() ); // chuck m_releaseTime = aTime; } // chuck MY_FLOAT ADSR :: getAttackTime() { return 1.0 / (attackRate*Stk::sampleRate()); } MY_FLOAT ADSR :: getDecayTime() { return (1.0 - sustainLevel) / (decayRate*Stk::sampleRate()); } MY_FLOAT ADSR :: getReleaseTime() { return sustainLevel / (releaseRate*Stk::sampleRate()); } void ADSR :: setAllTimes(MY_FLOAT aTime, MY_FLOAT dTime, MY_FLOAT sLevel, MY_FLOAT rTime) { this->setAttackTime(aTime); this->setDecayTime(dTime); this->setSustainLevel(sLevel); this->setReleaseTime(rTime); } void ADSR :: setTarget(MY_FLOAT aTarget) { target = aTarget; if (value < target) { state = ATTACK; this->setSustainLevel(target); rate = attackRate; } if (value > target) { this->setSustainLevel(target); state = DECAY; rate = decayRate; } } void ADSR :: setValue(MY_FLOAT aValue) { state = SUSTAIN; target = aValue; value = aValue; this->setSustainLevel(aValue); rate = (MY_FLOAT) 0.0; } int ADSR :: getState(void) const { return state; } MY_FLOAT ADSR :: tick() { switch(state) { case ATTACK: value += rate; if (value >= target) { value = target; rate = decayRate; target = sustainLevel; state = DECAY; // TODO: check this if( decayRate >= FLT_MAX ) // big number { // go directly to sustain; state = SUSTAIN; value = sustainLevel; rate = 0.0; } } break; case DECAY: value -= decayRate; if (value <= sustainLevel) { value = sustainLevel; rate = (MY_FLOAT) 0.0; state = SUSTAIN; } break; case RELEASE: value -= releaseRate; if (value <= 0.0) { value = (MY_FLOAT) 0.0; state = DONE; } } return value; } MY_FLOAT *ADSR :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i BandedWG :: BandedWG() { doPluck = true; delay = new DelayL[MAX_BANDED_MODES]; bandpass = new BiQuad[MAX_BANDED_MODES]; bowTabl = new BowTabl; bowTabl->setSlope( 3.0 ); adsr = new ADSR; adsr->setAllTimes( 0.02, 0.005, 0.9, 0.01 ); freakency = 220.0; setPreset(0); bowPosition = 0; baseGain = (MY_FLOAT) 0.999; integrationConstant = 0.0; trackVelocity = false; bowVelocity = 0.0; bowTarget = 0.0; strikeAmp = 0.0; // chuck m_frequency = freakency; // rate m_rate = .02; // reverse: nothing (set directly from norm in controlChange) m_bowPressure = 0.0; // reverse: bowPosition m_bowMotion = bowPosition; // reverse: baseGain = 0.8999999999999999 + (0.1 * norm); m_modesGain = (baseGain - 0.8999999999999999) / .1; // reverse: nothing (set directly from preset in setPreset) m_preset = 0; // reverse: not used m_strikePosition = 0; } BandedWG :: ~BandedWG() { delete bowTabl; delete adsr; delete [] bandpass; delete [] delay; } void BandedWG :: clear() { for (int i=0; i 1568.0) freakency = 1568.0; MY_FLOAT radius; MY_FLOAT base = Stk::sampleRate() / freakency; MY_FLOAT length; for (int i=0; i 2.0) { delay[i].setDelay( length ); gains[i]=basegains[i]; // gains[i]=(MY_FLOAT) pow(basegains[i], 1/((MY_FLOAT)delay[i].getDelay())); // std::cerr << gains[i]; } else { nModes = i; break; } // std::cerr << std::endl; // Set the bandpass filter resonances radius = 1.0 - ONE_PI * 32 / Stk::sampleRate(); //freakency * modes[i] / Stk::sampleRate()/32; if ( radius < 0.0 ) radius = 0.0; bandpass[i].setResonance(freakency * modes[i], radius, true); delay[i].clear(); bandpass[i].clear(); } //int olen = (int)(delay[0].getDelay()); //strikePosition = (int)(strikePosition*(length/modes[0])/olen); // chuck m_frequency = freakency; } void BandedWG :: setStrikePosition(MY_FLOAT position) { strikePosition = (int)(delay[0].getDelay() * position / 2.0); m_strikePosition = position; } void BandedWG :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOn(); maxVelocity = 0.03 + (0.1 * amplitude); } void BandedWG :: stopBowing(MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOff(); } void BandedWG :: pluck(MY_FLOAT amplitude) { int j; MY_FLOAT min_len = delay[nModes-1].getDelay(); for (int i=0; isetFrequency(frequency); if ( doPluck ) this->pluck(amplitude); else this->startBowing(amplitude, amplitude * 0.001); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BandedWG: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void BandedWG :: noteOff(MY_FLOAT amplitude) { if ( !doPluck ) this->stopBowing((1.0 - amplitude) * 0.005); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BandedWG: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT BandedWG :: tick() { int k; MY_FLOAT input = 0.0; if ( doPluck ) { input = 0.0; // input = strikeAmp/nModes; // strikeAmp = 0.0; } else { if (integrationConstant == 0.0) velocityInput = 0.0; else velocityInput = integrationConstant * velocityInput; for (k=0; ktick() * maxVelocity; input = bowVelocity - velocityInput; input = input * bowTabl->tick(input); input = input/(MY_FLOAT)nModes; } MY_FLOAT data = 0.0; for (k=0; k 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): BandedWG: Control value greater than 128.0!" << std::endl; } if (number == __SK_BowPressure_) { // 2 m_bowPressure = norm; if ( norm == 0.0 ) doPluck = true; else { doPluck = false; bowTabl->setSlope( 10.0 - (9.0 * norm)); } } else if (number == 4) { // 4 if ( !trackVelocity ) trackVelocity = true; bowTarget += 0.005 * (norm - bowPosition); bowPosition = norm; m_bowMotion = norm; //adsr->setTarget(bowPosition); } else if (number == 8) // 8 this->setStrikePosition( norm ); else if (number == __SK_AfterTouch_Cont_) { // 128 //bowTarget += 0.02 * (norm - bowPosition); //bowPosition = norm; if ( trackVelocity ) trackVelocity = false; maxVelocity = 0.13 * norm; adsr->setTarget(norm); } else if (number == __SK_ModWheel_) { // 1 // baseGain = 0.9989999999 + (0.001 * norm ); baseGain = 0.8999999999999999 + (0.1 * norm); // std::cerr << "[chuck](via STK): Yuck!" << std::endl; for (int i=0; isetPreset((int) value); else std::cerr << "[chuck](via STK): BandedWG: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BandedWG: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class BeeThree \brief STK Hammond-oid organ FM synthesis instrument. This class implements a simple 4 operator topology, also referred to as algorithm 8 of the TX81Z. \code Algorithm 8 is : 1 --. 2 -\| +-> Out 3 -/| 4 -- \endcode Control Change Numbers: - Operator 4 (feedback) Gain = 2 - Operator 3 Gain = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ BeeThree :: BeeThree() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( (Stk::rawwavePath() + "special:sinewave").c_str(), TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 0.999); this->setRatio(1, 1.997); this->setRatio(2, 3.006); this->setRatio(3, 6.009); gains[0] = __FM_gains[95]; gains[1] = __FM_gains[95]; gains[2] = __FM_gains[99]; gains[3] = __FM_gains[95]; adsr[0]->setAllTimes( 0.005, 0.003, 1.0, 0.01); adsr[1]->setAllTimes( 0.005, 0.003, 1.0, 0.01); adsr[2]->setAllTimes( 0.005, 0.003, 1.0, 0.01); adsr[3]->setAllTimes( 0.005, 0.001, 0.4, 0.03); twozero->setGain( 0.1 ); } BeeThree :: ~BeeThree() { } void BeeThree :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[95]; gains[1] = amplitude * __FM_gains[95]; gains[2] = amplitude * __FM_gains[99]; gains[3] = amplitude * __FM_gains[95]; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "BeeThree: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT BeeThree :: tick() { register MY_FLOAT temp; if (modDepth > 0.0) { temp = 1.0 + (modDepth * vibrato->tick() * 0.1); waves[0]->setFrequency(baseFrequency * temp * ratios[0]); waves[1]->setFrequency(baseFrequency * temp * ratios[1]); waves[2]->setFrequency(baseFrequency * temp * ratios[2]); waves[3]->setFrequency(baseFrequency * temp * ratios[3]); } waves[3]->addPhaseOffset(twozero->lastOut()); temp = control1 * 2.0 * gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); temp += control2 * 2.0 * gains[2] * adsr[2]->tick() * waves[2]->tick(); temp += gains[1] * adsr[1]->tick() * waves[1]->tick(); temp += gains[0] * adsr[0]->tick() * waves[0]->tick(); lastOutput = temp * 0.125; return lastOutput; } /***************************************************/ /*! \class BiQuad \brief STK biquad (two-pole, two-zero) filter class. This protected Filter subclass implements a two-pole, two-zero digital filter. A method is provided for creating a resonance in the frequency response while maintaining a constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include BiQuad :: BiQuad() : FilterStk() { MY_FLOAT B[3] = {1.0, 0.0, 0.0}; MY_FLOAT A[3] = {1.0, 0.0, 0.0}; FilterStk::setCoefficients( 3, B, 3, A ); } BiQuad :: ~BiQuad() { } void BiQuad :: clear(void) { FilterStk::clear(); } void BiQuad :: setB0(MY_FLOAT b0) { b[0] = b0; } void BiQuad :: setB1(MY_FLOAT b1) { b[1] = b1; } void BiQuad :: setB2(MY_FLOAT b2) { b[2] = b2; } void BiQuad :: setA1(MY_FLOAT a1) { a[1] = a1; } void BiQuad :: setA2(MY_FLOAT a2) { a[2] = a2; } void BiQuad :: setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize) { a[2] = radius * radius; a[1] = -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate()); if ( normalize ) { // Use zeros at +- 1 and normalize the filter peak gain. b[0] = 0.5 - 0.5 * a[2]; b[1] = 0.0; b[2] = -b[0]; } } void BiQuad :: setNotch(MY_FLOAT frequency, MY_FLOAT radius) { // This method does not attempt to normalize the filter gain. b[2] = radius * radius; b[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate()); } void BiQuad :: setEqualGainZeroes() { b[0] = 1.0; b[1] = 0.0; b[2] = -1.0; } void BiQuad :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT BiQuad :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT BiQuad :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT BiQuad :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[0] * inputs[0] + b[1] * inputs[1] + b[2] * inputs[2]; outputs[0] -= a[2] * outputs[2] + a[1] * outputs[1]; inputs[2] = inputs[1]; inputs[1] = inputs[0]; outputs[2] = outputs[1]; outputs[1] = outputs[0]; // gewang: dedenormal CK_STK_DDN(outputs[1]); CK_STK_DDN(outputs[2]); return outputs[0]; } MY_FLOAT *BiQuad :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i #include Blit:: Blit( MY_FLOAT frequency ) { nHarmonics_ = 0; this->setFrequency( frequency ); this->reset(); } Blit :: ~Blit() { } void Blit :: reset() { phase_ = 0.0; // lastOutput_ = 0; } void Blit :: setFrequency( MY_FLOAT frequency ) { #if defined(_STK_DEBUG_) errorString_ << "Blit::setFrequency: frequency = " << frequency << '.'; handleError( StkError::DEBUG_WARNING ); #endif p_ = Stk::sampleRate() / frequency; rate_ = ONE_PI / p_; this->updateHarmonics(); } void Blit :: setHarmonics( unsigned int nHarmonics ) { nHarmonics_ = nHarmonics; this->updateHarmonics(); } void Blit :: updateHarmonics( void ) { if ( nHarmonics_ <= 0 ) { unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); m_ = 2 * maxHarmonics + 1; } else m_ = 2 * nHarmonics_ + 1; #if defined(_STK_DEBUG_) errorString_ << "Blit::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.'; handleError( StkError::DEBUG_WARNING ); #endif } MY_FLOAT Blit :: tick( void ) { // The code below implements the SincM algorithm of Stilson and // Smith with an additional scale factor of P / M applied to // normalize the output. // A fully optimized version of this code would replace the two sin // calls with a pair of fast sin oscillators, for which stable fast // two-multiply algorithms are well known. In the spirit of STK, // which favors clarity over performance, the optimization has not // been made here. MY_FLOAT output; // Avoid a divide by zero at the sinc peak, which has a limiting // value of 1.0. MY_FLOAT denominator = sin( phase_ ); if ( denominator <= std::numeric_limits::epsilon() ) { output = 1.0; } else { output = sin( m_ * phase_ ); output /= m_ * denominator; } phase_ += rate_; if ( phase_ >= ONE_PI ) phase_ -= ONE_PI; return output; } /***************************************************/ /*! \class BlitSaw \brief STK band-limited sawtooth wave class. This class generates a band-limited sawtooth waveform using a closed-form algorithm reported by Stilson and Smith in "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. The user can specify both the fundamental frequency of the sawtooth and the number of harmonics contained in the resulting signal. If nHarmonics is 0, then the signal will contain all harmonics up to half the sample rate. Note, however, that this setting may produce aliasing in the signal when the frequency is changing (no automatic modification of the number of harmonics is performed by the setFrequency() function). Based on initial code of Robin Davies, 2005. Modified algorithm code by Gary Scavone, 2005. */ /***************************************************/ BlitSaw:: BlitSaw( MY_FLOAT frequency ) { nHarmonics_ = 0; this->reset(); this->setFrequency( frequency ); } BlitSaw :: ~BlitSaw() { } void BlitSaw :: reset() { phase_ = 0.0f; state_ = 0.0; // lastOutput_ = 0; } void BlitSaw :: setFrequency( MY_FLOAT frequency ) { #if defined(_STK_DEBUG_) errorString_ << "BlitSaw::setFrequency: frequency = " << frequency << '.'; handleError( StkError::DEBUG_WARNING ); #endif p_ = Stk::sampleRate() / frequency; C2_ = 1 / p_; rate_ = ONE_PI * C2_; this->updateHarmonics(); } void BlitSaw :: setHarmonics( unsigned int nHarmonics ) { nHarmonics_ = nHarmonics; this->updateHarmonics(); // I found that the initial DC offset could be minimized with an // initial state setting as given below. This initialization should // only happen before starting the oscillator for the first time // (but after setting the frequency and number of harmonics). I // struggled a bit to decide where best to put this and finally // settled on here. In general, the user shouldn't be messing with // the number of harmonics once the oscillator is running because // this is automatically taken care of in the setFrequency() // function. (GPS - 1 October 2005) state_ = -0.5 * a_; } void BlitSaw :: updateHarmonics( void ) { if ( nHarmonics_ <= 0 ) { unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); m_ = 2 * maxHarmonics + 1; } else m_ = 2 * nHarmonics_ + 1; a_ = m_ / p_; #if defined(_STK_DEBUG_) errorString_ << "BlitSaw::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.'; handleError( StkError::DEBUG_WARNING ); #endif } MY_FLOAT BlitSaw :: tick( void ) { // The code below implements the BLIT algorithm of Stilson and // Smith, followed by a summation and filtering operation to produce // a sawtooth waveform. After experimenting with various approaches // to calculate the average value of the BLIT over one period, I // found that an estimate of C2_ = 1.0 / period (in samples) worked // most consistently. A "leaky integrator" is then applied to the // difference of the BLIT output and C2_. (GPS - 1 October 2005) // A fully optimized version of this code would replace the two sin // calls with a pair of fast sin oscillators, for which stable fast // two-multiply algorithms are well known. In the spirit of STK, // which favors clarity over performance, the optimization has // not been made here. MY_FLOAT output; // Avoid a divide by zero, or use of a denormalized divisor // at the sinc peak, which has a limiting value of m_ / p_. MY_FLOAT denominator = sin( phase_ ); if ( fabs(denominator) <= std::numeric_limits::epsilon() ) output = a_; else { output = sin( m_ * phase_ ); output /= p_ * denominator; } output += state_ - C2_; state_ = output * 0.995; phase_ += rate_; if ( phase_ >= ONE_PI ) phase_ -= ONE_PI; return output; } /***************************************************/ /*! \class BlitSquare \brief STK band-limited square wave class. This class generates a band-limited square wave signal. It is derived in part from the approach reported by Stilson and Smith in "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. The algorithm implemented in this class uses a SincM function with an even M value to achieve a bipolar bandlimited impulse train. This signal is then integrated to achieve a square waveform. The integration process has an associated DC offset but that is subtracted off the output signal. The user can specify both the fundamental frequency of the waveform and the number of harmonics contained in the resulting signal. If nHarmonics is 0, then the signal will contain all harmonics up to half the sample rate. Note, however, that this setting may produce aliasing in the signal when the frequency is changing (no automatic modification of the number of harmonics is performed by the setFrequency() function). Based on initial code of Robin Davies, 2005. Modified algorithm code by Gary Scavone, 2005. */ /***************************************************/ BlitSquare:: BlitSquare( MY_FLOAT frequency ) { nHarmonics_ = 0; this->setFrequency( frequency ); this->reset(); } BlitSquare :: ~BlitSquare() { } void BlitSquare :: reset() { phase_ = 0.0; m_output = 0; dcbState_ = 0.0; m_boutput = 0.0; } void BlitSquare :: setFrequency( MY_FLOAT frequency ) { #if defined(_STK_DEBUG_) errorString_ << "BlitSquare::setFrequency: frequency = " << frequency << '.'; handleError( StkError::DEBUG_WARNING ); #endif // By using an even value of the parameter M, we get a bipolar blit // waveform at half the blit frequency. Thus, we need to scale the // frequency value here by 0.5. (GPS, 2006). p_ = 0.5 * Stk::sampleRate() / frequency; rate_ = ONE_PI / p_; this->updateHarmonics(); } void BlitSquare :: setHarmonics( unsigned int nHarmonics ) { nHarmonics_ = nHarmonics; this->updateHarmonics(); } void BlitSquare :: updateHarmonics( void ) { // Make sure we end up with an even value of the parameter M here. if ( nHarmonics_ <= 0 ) { unsigned int maxHarmonics = (unsigned int) floor( 0.5 * p_ ); m_ = 2 * ( maxHarmonics ); } else m_ = 2 * ( nHarmonics_ ); // This offset value was derived empirically. (GPS, 2005) // offset_ = 1.0 - 0.5 * m_ / p_; a_ = m_ / p_; #if defined(_STK_DEBUG_) errorString_ << "BlitSquare::updateHarmonics: nHarmonics_ = " << nHarmonics_ << ", m_ = " << m_ << '.'; handleError( StkError::DEBUG_WARNING ); #endif } MY_FLOAT BlitSquare :: tick( void ) { MY_FLOAT temp = m_boutput; // A fully optimized version of this would replace the two sin calls // with a pair of fast sin oscillators, for which stable fast // two-multiply algorithms are well known. In the spirit of STK, // which favors clarity over performance, the optimization has // not been made here. // Avoid a divide by zero, or use of a denomralized divisor // at the sinc peak, which has a limiting value of 1.0. MY_FLOAT denominator = sin( phase_ ); if ( fabs( denominator ) < std::numeric_limits::epsilon() ) { // Inexact comparison safely distinguishes betwen *close to zero*, and *close to PI*. if ( phase_ < 0.1f || phase_ > TWO_PI - 0.1f ) m_boutput = a_; else m_boutput = -a_; } else { m_boutput = sin( m_ * phase_ ); m_boutput /= p_ * denominator; } m_boutput += temp; // Now apply DC blocker. m_output = m_boutput - dcbState_ + 0.999 * m_output; dcbState_ = m_boutput; phase_ += rate_; if ( phase_ >= TWO_PI ) phase_ -= TWO_PI; return m_output; } /***************************************************/ /*! \class BlowBotl \brief STK blown bottle instrument class. This class implements a helmholtz resonator (biquad filter) with a polynomial jet excitation (a la Cook). Control Change Numbers: - Noise Gain = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #define __BOTTLE_RADIUS_ 0.999 BlowBotl :: BlowBotl() { jetTable = new JetTabl(); dcBlock = new PoleZero(); dcBlock->setBlockZero(); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency( 5.925 ); vibratoGain = 0.0; resonator = new BiQuad(); resonator->setResonance(500.0, __BOTTLE_RADIUS_, true); adsr = new ADSR(); adsr->setAllTimes( 0.005, 0.01, 0.8, 0.010 ); noise = new Noise(); noiseGain = 20.0; maxPressure = (MY_FLOAT)0.0; // chuck added later outputGain = 1.0; // chuck //reverse: nothing (set from directly from setFrequency) m_frequency = 500; //reverse: nothing (set in BlowBotl_ctrl_rate only) m_rate = .02; //reverse: norm * 30.0 (from controlChange) m_noiseGain = noiseGain / 30.0; //reverse: vibratoFreq * 12.0 (from controlChange) m_vibratoFreq = vibrato->m_freq / 12.0; //reverse: vibratoGain * 0.4 (from controlChange) m_vibratoGain = vibratoGain / 0.4; //reverse: nothing (set in controlChange) m_volume = 1.0; } BlowBotl :: ~BlowBotl() { delete jetTable; delete resonator; delete dcBlock; delete noise; delete adsr; delete vibrato; } void BlowBotl :: clear() { resonator->clear(); } void BlowBotl :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): BlowBotl: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } resonator->setResonance( freakency, __BOTTLE_RADIUS_, true ); // chuck m_frequency = freakency; } void BlowBotl :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { adsr->setAttackRate(rate); maxPressure = amplitude; adsr->keyOn(); } void BlowBotl :: stopBlowing(MY_FLOAT rate) { adsr->setReleaseRate(rate); adsr->keyOff(); } void BlowBotl :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02); outputGain = amplitude + 0.001; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowBotl: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void BlowBotl :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.02); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowBotl: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT BlowBotl :: tick() { MY_FLOAT breathPressure; MY_FLOAT randPressure; MY_FLOAT pressureDiff; // Calculate the breath pressure (envelope + vibrato) breathPressure = maxPressure * adsr->tick(); breathPressure += vibratoGain * vibrato->tick(); pressureDiff = breathPressure - resonator->lastOut(); randPressure = noiseGain * noise->tick(); randPressure *= breathPressure; randPressure *= (1.0 + pressureDiff); resonator->tick( breathPressure + randPressure - ( jetTable->tick( pressureDiff ) * pressureDiff ) ); lastOutput = 0.2 * outputGain * dcBlock->tick( pressureDiff ); return lastOutput; } void BlowBotl :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): BlowBotl: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): BlowBotl: Control value greater than 128.0!" << std::endl; } if( number == __SK_NoiseLevel_ ) { // 4 noiseGain = norm * 30.0; m_noiseGain = norm; // chuck } else if( number == __SK_ModFrequency_ ) // 11 setVibratoFreq( norm * 12.0 ); else if( number == __SK_ModWheel_ ) { // 1 vibratoGain = norm * 0.4; m_vibratoGain = norm; } else if( number == __SK_AfterTouch_Cont_ ) { // 128 adsr->setTarget( norm ); m_volume = norm; } else std::cerr << "[chuck](via STK): BlowBotl: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowBotl: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class BlowHole \brief STK clarinet physical model with one register hole and one tonehole. This class is based on the clarinet model, with the addition of a two-port register hole and a three-port dynamic tonehole implementation, as discussed by Scavone and Cook (1998). In this implementation, the distances between the reed/register hole and tonehole/bell are fixed. As a result, both the tonehole and register hole will have variable influence on the playing frequency, which is dependent on the length of the air column. In addition, the highest playing freqeuency is limited by these fixed lengths. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Reed Stiffness = 2 - Noise Gain = 4 - Tonehole State = 11 - Register State = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include BlowHole :: BlowHole(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); // delays[0] is the delay line between the reed and the register vent. delays[0] = (DelayL *) new DelayL( 5.0 * Stk::sampleRate() / 22050.0, 100 ); // delays[1] is the delay line between the register vent and the tonehole. delays[1] = (DelayL *) new DelayL( length >> 1, length ); // delays[2] is the delay line between the tonehole and the end of the bore. delays[2] = (DelayL *) new DelayL( 4.0 * Stk::sampleRate() / 22050.0, 100 ); reedTable = new ReedTabl(); reedTable->setOffset((MY_FLOAT) 0.7); reedTable->setSlope((MY_FLOAT) -0.3); filter = new OneZero; envelope = new Envelope; noise = new Noise; // Calculate the initial tonehole three-port scattering coefficient double r_b = 0.0075; // main bore radius r_th = 0.003; // tonehole radius scatter = -pow(r_th,2) / ( pow(r_th,2) + 2*pow(r_b,2) ); // Calculate tonehole coefficients MY_FLOAT te = 1.4 * r_th; // effective length of the open hole th_coeff = (te*2*Stk::sampleRate() - 347.23) / (te*2*Stk::sampleRate() + 347.23); tonehole = new PoleZero; // Start with tonehole open tonehole->setA1(-th_coeff); tonehole->setB0(th_coeff); tonehole->setB1(-1.0); // Calculate register hole filter coefficients double r_rh = 0.0015; // register vent radius te = 1.4 * r_rh; // effective length of the open hole double xi = 0.0; // series resistance term double zeta = 347.23 + 2*ONE_PI*pow(r_b,2)*xi/1.1769; double psi = 2*ONE_PI*pow(r_b,2)*te / (ONE_PI*pow(r_rh,2)); rh_coeff = (zeta - 2 * Stk::sampleRate() * psi) / (zeta + 2 * Stk::sampleRate() * psi); rh_gain = -347.23 / (zeta + 2 * Stk::sampleRate() * psi); vent = new PoleZero; vent->setA1(rh_coeff); vent->setB0(1.0); vent->setB1(1.0); // Start with register vent closed vent->setGain(0.0); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency((MY_FLOAT) 5.735); outputGain = (MY_FLOAT) 1.0; noiseGain = (MY_FLOAT) 0.2; vibratoGain = (MY_FLOAT) 0.01; // set setFrequency( 220.0 ); // chuck data //m_reed = 0.5; // DONE: check default value <- old value //reverse: slope = -0.44 + (0.26 * norm) m_reed = (reedTable->slope + 0.44) / 0.26; //reverse: noiseGain = norm * 0.4 m_noiseGain = noiseGain / .4; //reverse: nothing m_tonehole = 1.0; //reverse: nothing m_vent = 0.0; //reverse: nothing m_pressure = 1.0; //reverse: nothing m_rate = envelope->rate; } BlowHole :: ~BlowHole() { delete delays[0]; delete delays[1]; delete delays[2]; delete reedTable; delete filter; delete tonehole; delete vent; delete envelope; delete noise; delete vibrato; } void BlowHole :: clear() { delays[0]->clear(); delays[1]->clear(); delays[2]->clear(); filter->tick((MY_FLOAT) 0.0); tonehole->tick((MY_FLOAT) 0.0); vent->tick((MY_FLOAT) 0.0); } void BlowHole :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): BlowHole: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // Delay = length - approximate filter delay. MY_FLOAT delay = (Stk::sampleRate() / freakency) * 0.5 - 3.5; delay -= delays[0]->getDelay() + delays[2]->getDelay(); if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; delays[1]->setDelay(delay); // chuck m_frequency = freakency; } void BlowHole :: setVent(MY_FLOAT newValue) { // This method allows setting of the register vent "open-ness" at // any point between "Open" (newValue = 1) and "Closed" // (newValue = 0). MY_FLOAT gain; if (newValue <= 0.0) gain = 0.0; else if (newValue >= 1.0) gain = rh_gain; else gain = newValue * rh_gain; m_vent = newValue; vent->setGain(gain); } void BlowHole :: setTonehole(MY_FLOAT newValue) { // This method allows setting of the tonehole "open-ness" at // any point between "Open" (newValue = 1) and "Closed" // (newValue = 0). MY_FLOAT new_coeff; if (newValue <= 0.0) new_coeff = 0.9995; else if (newValue >= 1.0) new_coeff = th_coeff; else new_coeff = (newValue * (th_coeff - 0.9995)) + 0.9995; m_tonehole = newValue; tonehole->setA1(-new_coeff); tonehole->setB0(new_coeff); } void BlowHole :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget(amplitude); } void BlowHole :: stopBlowing(MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget((MY_FLOAT) 0.0); } void BlowHole :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); startBlowing((MY_FLOAT) 0.55 + (amplitude * 0.30), amplitude * 0.005); outputGain = amplitude + 0.001; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowHole: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void BlowHole :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.01); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowHole: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT BlowHole :: tick() { MY_FLOAT pressureDiff; MY_FLOAT breathPressure; MY_FLOAT temp; // Calculate the breath pressure (envelope + noise + vibrato) breathPressure = envelope->tick(); breathPressure += breathPressure * noiseGain * noise->tick(); breathPressure += breathPressure * vibratoGain * vibrato->tick(); // Calculate the differential pressure = reflected - mouthpiece pressures pressureDiff = delays[0]->lastOut() - breathPressure; // Do two-port junction scattering for register vent MY_FLOAT pa = breathPressure + pressureDiff * reedTable->tick(pressureDiff); MY_FLOAT pb = delays[1]->lastOut(); vent->tick(pa+pb); lastOutput = delays[0]->tick(vent->lastOut()+pb); lastOutput *= outputGain; // Do three-port junction scattering (under tonehole) pa += vent->lastOut(); pb = delays[2]->lastOut(); MY_FLOAT pth = tonehole->lastOut(); temp = scatter * (pa + pb - 2 * pth); delays[2]->tick(filter->tick(pa + temp) * -0.95); delays[1]->tick(pb + temp); tonehole->tick(pa + pb - pth + temp); return lastOutput; } void BlowHole :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): BlowHole: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): BlowHole: Control value greater than 128.0!" << std::endl; } if (number == __SK_ReedStiffness_) { // 2 m_reed = norm; reedTable->setSlope( -0.44 + (0.26 * norm) ); } else if (number == __SK_NoiseLevel_) { // 4 m_noiseGain = norm; noiseGain = ( norm * 0.4 ); } else if (number == __SK_ModFrequency_) // 11 this->setTonehole( norm ); else if (number == __SK_ModWheel_) // 1 this->setVent( norm ); else if (number == __SK_AfterTouch_Cont_) { // 128 m_pressure = norm; envelope->setValue( norm ); } else std::cerr << "[chuck](via STK): BlowHole: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): BlowHole: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class BowTabl \brief STK bowed string table class. This class implements a simple bowed string non-linear function, as described by Smith (1986). by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include BowTabl :: BowTabl() { offSet = (MY_FLOAT) 0.0; slope = (MY_FLOAT) 0.1; } BowTabl :: ~BowTabl() { } void BowTabl :: setOffset(MY_FLOAT aValue) { offSet = aValue; } void BowTabl :: setSlope(MY_FLOAT aValue) { slope = aValue; } MY_FLOAT BowTabl :: lastOut() const { return lastOutput; } MY_FLOAT BowTabl :: tick(MY_FLOAT input) { // The input represents differential string vs. bow velocity. MY_FLOAT sample; sample = input + offSet; // add bias to input sample *= slope; // then scale it lastOutput = (MY_FLOAT) fabs((double) sample) + (MY_FLOAT) 0.75; lastOutput = (MY_FLOAT) pow( lastOutput,(MY_FLOAT) -4.0 ); // Set minimum friction to 0.0 //if (lastOutput < 0.0 ) lastOutput = 0.0; // Set maximum friction to 1.0. if (lastOutput > 1.0 ) lastOutput = (MY_FLOAT) 1.0; return lastOutput; } MY_FLOAT *BowTabl :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i>= 1; bridgeDelay = new DelayL(29.0, length); bowTable = new BowTabl; bowTable->setSlope((MY_FLOAT) 3.0); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency((MY_FLOAT) 6.12723); vibratoGain = (MY_FLOAT) 0.0; stringFilter = new OnePole; stringFilter->setPole((MY_FLOAT) (0.6 - (0.1 * 22050.0 / Stk::sampleRate() ) ) ); stringFilter->setGain((MY_FLOAT) 0.95); bodyFilter = new BiQuad; bodyFilter->setResonance( 500.0, 0.85, TRUE ); bodyFilter->setGain((MY_FLOAT) 0.2); adsr = new ADSR; adsr->setAllTimes((MY_FLOAT) 0.02,(MY_FLOAT) 0.005,(MY_FLOAT) 0.9,(MY_FLOAT) 0.01); betaRatio = (MY_FLOAT)0.127236; // Necessary to initialize internal variables. setFrequency( 220.0 ); // CHUCK //reverse: bowTable->setSlope( 5.0 - (4.0 * norm) ); m_bowPressure = (bowTable->slope - 5.0) / -4.0; //reverse: betaRatio = 0.027236 + (0.2 * norm); m_bowPosition = (betaRatio - .027236) / .2; //reverse: setVibratoFreq( norm * 12.0 ); m_vibratoFreq = vibrato->m_freq / 12.0; //reverse: vibratoGain = ( norm * 0.4 ); m_vibratoGain = 0.0; // vibratoGain / 0.4 //reverse: nothing m_volume = 1.0; } Bowed :: ~Bowed() { delete neckDelay; delete bridgeDelay; delete bowTable; delete stringFilter; delete bodyFilter; delete vibrato; delete adsr; } void Bowed :: clear() { neckDelay->clear(); bridgeDelay->clear(); } void Bowed :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Bowed: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // Delay = length - approximate filter delay. baseDelay = Stk::sampleRate() / freakency - (MY_FLOAT) 4.0; if ( baseDelay <= 0.0 ) baseDelay = 0.3; bridgeDelay->setDelay(baseDelay * betaRatio); // bow to bridge length neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); // bow to nut (finger) length // chuck m_frequency = freakency; } void Bowed :: startBowing(MY_FLOAT amplitude, MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOn(); maxVelocity = (MY_FLOAT) 0.03 + ((MY_FLOAT) 0.2 * amplitude); } void Bowed :: stopBowing(MY_FLOAT rate) { adsr->setRate(rate); adsr->keyOff(); } void Bowed :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->startBowing(amplitude, amplitude * 0.001); this->setFrequency(frequency); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Bowed: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Bowed :: noteOff(MY_FLOAT amplitude) { this->stopBowing(((MY_FLOAT) 1.0 - amplitude) * (MY_FLOAT) 0.005); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Bowed: NoteOff amplitude = " << amplitude << std::endl; #endif } void Bowed :: setVibrato(MY_FLOAT gain) { vibratoGain = gain; } MY_FLOAT Bowed :: tick() { MY_FLOAT bowVelocity; MY_FLOAT bridgeRefl; MY_FLOAT nutRefl; MY_FLOAT newVel; MY_FLOAT velDiff; MY_FLOAT stringVel; bowVelocity = maxVelocity * adsr->tick(); bridgeRefl = -stringFilter->tick( bridgeDelay->lastOut() ); nutRefl = -neckDelay->lastOut(); stringVel = bridgeRefl + nutRefl; // Sum is String Velocity velDiff = bowVelocity - stringVel; // Differential Velocity newVel = velDiff * bowTable->tick( velDiff ); // Non-Linear Bow Function neckDelay->tick(bridgeRefl + newVel); // Do string propagations bridgeDelay->tick(nutRefl + newVel); if (vibratoGain > 0.0) { neckDelay->setDelay((baseDelay * ((MY_FLOAT) 1.0 - betaRatio)) + (baseDelay * vibratoGain * vibrato->tick())); } lastOutput = bodyFilter->tick(bridgeDelay->lastOut()); return lastOutput; } void Bowed :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Bowed: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Bowed: Control value greater than 128.0!" << std::endl; } if (number == __SK_BowPressure_) { // 2 m_bowPressure = norm; bowTable->setSlope( 5.0 - (4.0 * norm) ); } else if (number == __SK_BowPosition_) { // 4 m_bowPosition = norm; betaRatio = 0.027236 + (0.2 * norm); bridgeDelay->setDelay(baseDelay * betaRatio); neckDelay->setDelay(baseDelay * ((MY_FLOAT) 1.0 - betaRatio)); } else if (number == __SK_ModFrequency_) { // 11 setVibratoFreq( norm * 12.0 ); m_vibratoFreq = norm; } else if (number == __SK_ModWheel_) { // 1 m_vibratoGain = norm; vibratoGain = ( norm * 0.4 ); } else if (number == __SK_AfterTouch_Cont_) { // 128 m_volume = norm; adsr->setTarget(norm); } else std::cerr << "[chuck](via STK): Bowed: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Bowed: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Brass \brief STK simple brass instrument class. This class implements a simple brass instrument waveguide model, a la Cook (TBone, HosePlayer). This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Lip Tension = 2 - Slide Length = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Brass :: Brass(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); delayLine = new DelayA( 0.5 * length, length ); lipFilter = new BiQuad(); lipFilter->setGain( 0.03 ); dcBlock = new PoleZero(); dcBlock->setBlockZero(); adsr = new ADSR; adsr->setAllTimes( 0.005, 0.001, 1.0, 0.010); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency( 6.137 ); vibratoGain = 0.0; this->clear(); maxPressure = (MY_FLOAT) 0.0; lipTarget = 0.0; // Necessary to initialize variables. setFrequency( 220.0 ); // CHUCK //reverse: nothing m_rate = .005; //reverse: I give up! m_lip = 0.1; //reverse: this is a special variable... we'll just leave this be for now m_slide = length; //reverse: setVibratoFreq( norm * 12.0 ); m_vibratoFreq = vibrato->m_freq / 12.0; //reverse: setVibratoGain(norm * 0.4) m_vibratoGain = 0.0; //reverse: nothing m_volume = 1.0; } Brass :: ~Brass() { delete delayLine; delete lipFilter; delete dcBlock; delete adsr; delete vibrato; } void Brass :: clear() { delayLine->clear(); lipFilter->clear(); dcBlock->clear(); } void Brass :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Brass: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // Fudge correction for filter delays. slideTarget = (Stk::sampleRate() / freakency * 2.0) + 3.0; delayLine->setDelay(slideTarget); // play a harmonic lipTarget = freakency; lipFilter->setResonance( freakency, 0.997 ); // chuck m_frequency = freakency; } void Brass :: setLip(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Brass: setLip parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } lipFilter->setResonance( freakency, 0.997 ); } void Brass :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { adsr->setAttackRate(rate); maxPressure = amplitude; adsr->keyOn(); } void Brass :: stopBlowing(MY_FLOAT rate) { adsr->setReleaseRate(rate); adsr->keyOff(); } void Brass :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); this->startBlowing(amplitude, amplitude * 0.001); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Brass: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Brass :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.005); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Brass: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Brass :: tick() { MY_FLOAT breathPressure = maxPressure * adsr->tick(); breathPressure += vibratoGain * vibrato->tick(); MY_FLOAT mouthPressure = 0.3 * breathPressure; MY_FLOAT borePressure = 0.85 * delayLine->lastOut(); MY_FLOAT deltaPressure = mouthPressure - borePressure; // Differential pressure. deltaPressure = lipFilter->tick( deltaPressure ); // Force - > position. deltaPressure *= deltaPressure; // Basic position to area mapping. if ( deltaPressure > 1.0 ) deltaPressure = 1.0; // Non-linear saturation. // The following input scattering assumes the mouthPressure = area. lastOutput = deltaPressure * mouthPressure + ( 1.0 - deltaPressure) * borePressure; lastOutput = delayLine->tick( dcBlock->tick( lastOutput ) ); return lastOutput; } void Brass :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Brass: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Brass: Control value greater than 128.0!" << std::endl; } if (number == __SK_LipTension_) { // 2 MY_FLOAT temp = lipTarget * pow( 4.0, (2.0 * norm) - 1.0 ); m_lip = norm; this->setLip(temp); } else if (number == __SK_SlideLength_) { // 4 m_slide = norm; delayLine->setDelay( slideTarget * (0.5 + norm) ); } else if (number == __SK_ModFrequency_) // 11 setVibratoFreq( norm * 12.0 ); else if (number == __SK_ModWheel_ ) { // 1 m_vibratoGain = norm; vibratoGain = norm * 0.4; } else if (number == __SK_AfterTouch_Cont_) { // 128 m_volume = norm; adsr->setTarget( norm ); } else std::cerr << "[chuck](via STK): Brass: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Brass: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Chorus \brief STK chorus effect class. This class implements a chorus effect. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Chorus :: Chorus(MY_FLOAT baseDelay) { delayLine[0] = new DelayL((long) baseDelay, (long) (baseDelay * 1.414) + 2); delayLine[1] = new DelayL((long) (baseDelay), (long) baseDelay + 2); baseLength = baseDelay; // Concatenate the STK rawwave path to the rawwave file mods[0] = new WaveLoop( "special:sinewave", TRUE ); mods[1] = new WaveLoop( "special:sinewave", TRUE ); mods[0]->setFrequency(0.2); mods[1]->setFrequency(0.222222); modDepth = 0.05; effectMix = 0.5; this->clear(); } Chorus :: ~Chorus() { delete delayLine[0]; delete delayLine[1]; delete mods[0]; delete mods[1]; } void Chorus :: clear() { delayLine[0]->clear(); delayLine[1]->clear(); lastOutput[0] = 0.0; lastOutput[1] = 0.0; } void Chorus :: setEffectMix(MY_FLOAT mix) { effectMix = mix; if ( mix < 0.0 ) { std::cerr << "[chuck](via STK): Chorus: setEffectMix parameter is less than zero!" << std::endl; effectMix = 0.0; } else if ( mix > 1.0 ) { std::cerr << "[chuck](via STK): Chorus: setEffectMix parameter is greater than 1.0!" << std::endl; effectMix = 1.0; } } void Chorus :: setModDepth(MY_FLOAT depth) { modDepth = depth; } void Chorus :: setModFrequency(MY_FLOAT frequency) { mods[0]->setFrequency(frequency); mods[1]->setFrequency(frequency * 1.1111); } MY_FLOAT Chorus :: lastOut() const { return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5; } MY_FLOAT Chorus :: lastOutLeft() const { return lastOutput[0]; } MY_FLOAT Chorus :: lastOutRight() const { return lastOutput[1]; } MY_FLOAT Chorus :: tick(MY_FLOAT input) { delayLine[0]->setDelay(baseLength * 0.707 * (1.0 + mods[0]->tick())); delayLine[1]->setDelay(baseLength * 0.5 * (1.0 - mods[1]->tick())); lastOutput[0] = input * (1.0 - effectMix); lastOutput[0] += effectMix * delayLine[0]->tick(input); lastOutput[1] = input * (1.0 - effectMix); lastOutput[1] += effectMix * delayLine[1]->tick(input); return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5; } MY_FLOAT *Chorus :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; isetOffset((MY_FLOAT) 0.7); reedTable->setSlope((MY_FLOAT) -0.3); filter = new OneZero; envelope = new Envelope; noise = new Noise; // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency((MY_FLOAT) 5.735); outputGain = (MY_FLOAT) 1.0; noiseGain = (MY_FLOAT) 0.2; vibratoGain = (MY_FLOAT) 0.1; // set setFrequency( 220.0 ); // CHUCK //reverse: reedTable->setSlope((MY_FLOAT) -0.44 + ( (MY_FLOAT) 0.26 * norm )) m_reed = (reedTable->slope + 0.44) / 0.26; //reverse: noiseGain = (norm * (MY_FLOAT) 0.4); m_noiseGain = noiseGain / .4; //reverse: setVibratoFreq( norm * 12.0 ); m_vibratoFreq = vibrato->m_freq / 12.0; //reverse: vibratoGain = (norm * (MY_FLOAT) 0.5); m_vibratoGain = .1 / 0.5; //reverse: nothing m_volume = 1.0; //reverse: nothing m_rate = .005; } Clarinet :: ~Clarinet() { delete delayLine; delete reedTable; delete filter; delete envelope; delete noise; delete vibrato; } void Clarinet :: clear() { delayLine->clear(); filter->tick((MY_FLOAT) 0.0); } void Clarinet :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Clarinet: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // Delay = length - approximate filter delay. MY_FLOAT delay = (Stk::sampleRate() / freakency) * 0.5 - 1.5; if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; delayLine->setDelay(delay); // chuck m_frequency = freakency; } void Clarinet :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget(amplitude); } void Clarinet :: stopBlowing(MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget((MY_FLOAT) 0.0); } void Clarinet :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); this->startBlowing((MY_FLOAT) 0.55 + (amplitude * (MY_FLOAT) 0.30), amplitude * (MY_FLOAT) 0.005); outputGain = amplitude + (MY_FLOAT) 0.001; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Clarinet: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Clarinet :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * (MY_FLOAT) 0.01); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Clarinet: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Clarinet :: tick() { MY_FLOAT pressureDiff; MY_FLOAT breathPressure; // Calculate the breath pressure (envelope + noise + vibrato) breathPressure = envelope->tick(); breathPressure += breathPressure * noiseGain * noise->tick(); breathPressure += breathPressure * vibratoGain * vibrato->tick(); // Perform commuted loss filtering. pressureDiff = -0.95 * filter->tick(delayLine->lastOut()); // Calculate pressure difference of reflected and mouthpiece pressures. pressureDiff = pressureDiff - breathPressure; // Perform non-linear scattering using pressure difference in reed function. lastOutput = delayLine->tick(breathPressure + pressureDiff * reedTable->tick(pressureDiff)); // Apply output gain. lastOutput *= outputGain; return lastOutput; } void Clarinet :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Clarinet: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Clarinet: Control value greater than 128.0!" << std::endl; } if (number == __SK_ReedStiffness_) { // 2 m_reed = norm; reedTable->setSlope((MY_FLOAT) -0.44 + ( (MY_FLOAT) 0.26 * norm )); } else if (number == __SK_NoiseLevel_) { // 4 m_noiseGain = norm; noiseGain = (norm * (MY_FLOAT) 0.4); } else if (number == __SK_ModFrequency_) { // 11 m_vibratoFreq = norm; setVibratoFreq( norm * 12.0 ); } else if (number == __SK_ModWheel_) { // 1 m_vibratoGain = norm; vibratoGain = (norm * (MY_FLOAT) 0.5); } else if (number == __SK_AfterTouch_Cont_) { // 128 m_volume = norm; envelope->setValue(norm); } else std::cerr << "[chuck](via STK): Clarinet: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Clarinet: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Delay \brief STK non-interpolating delay line class. This protected Filter subclass implements a non-interpolating digital delay-line. A fixed maximum length of 4095 and a delay of zero is set using the default constructor. Alternatively, the delay and maximum length can be set during instantiation with an overloaded constructor. A non-interpolating delay line is typically used in fixed delay-length applications, such as for reverberation. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Delay :: Delay() { this->set( 0, 4096 ); } Delay :: Delay(long theDelay, long maxDelay) { this->set( theDelay, maxDelay ); } void Delay :: set( long delay, long max ) { // Writing before reading allows delays from 0 to length-1. // If we want to allow a delay of maxDelay, we need a // delay-line of length = maxDelay+1. length = max+1; // We need to delete the previously allocated inputs. if( inputs ) delete [] inputs; inputs = new MY_FLOAT[length]; this->clear(); inPoint = 0; this->setDelay(delay); } Delay :: ~Delay() { } void Delay :: clear(void) { long i; for (i=0;i length-1) { // The value is too big. std::cerr << "[chuck](via STK): Delay: setDelay(" << theDelay << ") too big!" << std::endl; // Force delay to maxLength. outPoint = inPoint + 1; delay = length - 1; } else if (theDelay < 0 ) { std::cerr << "[chuck](via STK): Delay: setDelay(" << theDelay << ") less than zero!" << std::endl; outPoint = inPoint; delay = 0; } else { outPoint = inPoint - (long) theDelay; // read chases write delay = theDelay; } while (outPoint < 0) outPoint += length; // modulo maximum length } MY_FLOAT Delay :: getDelay(void) const { return delay; } MY_FLOAT Delay :: energy(void) const { int i; register MY_FLOAT e = 0; if (inPoint >= outPoint) { for (i=outPoint; i delay) { std::cerr << "[chuck](via STK): Delay: contentsAt(" << tapDelay << ") too big!" << std::endl; i = (long) delay; } long tap = inPoint - i; if (tap < 0) // Check for wraparound. tap += length; return inputs[tap]; } MY_FLOAT Delay :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT Delay :: nextOut(void) const { return inputs[outPoint]; } MY_FLOAT Delay :: tick(MY_FLOAT sample) { inputs[inPoint++] = sample; // Check for end condition if (inPoint == length) inPoint -= length; // Read out next value outputs[0] = inputs[outPoint++]; if (outPoint>=length) outPoint -= length; return outputs[0]; } MY_FLOAT *Delay :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i DelayA :: DelayA() { this->setDelay( 0.5 ); apInput = 0.0; doNextOut = true; } DelayA :: DelayA(MY_FLOAT theDelay, long maxDelay) { // Writing before reading allows delays from 0 to length-1. length = maxDelay+1; if ( length > 4096 ) { // We need to delete the previously allocated inputs. delete [] inputs; inputs = new MY_FLOAT[length]; this->clear(); } inPoint = 0; this->setDelay(theDelay); apInput = 0.0; doNextOut = true; } void DelayA :: set( MY_FLOAT delay, long max ) { // Writing before reading allows delays from 0 to length-1. // If we want to allow a delay of maxDelay, we need a // delay-line of length = maxDelay+1. length = max+1; // We need to delete the previously allocated inputs. if( inputs ) delete [] inputs; inputs = new MY_FLOAT[length]; this->clear(); inPoint = 0; this->setDelay(delay); apInput = 0.0; doNextOut = true; } DelayA :: ~DelayA() { } void DelayA :: clear() { Delay::clear(); apInput = 0.0; } void DelayA :: setDelay(MY_FLOAT theDelay) { MY_FLOAT outPointer; if (theDelay > length-1) { std::cerr << "[chuck](via STK): DelayA: setDelay(" << theDelay << ") too big!" << std::endl; // Force delay to maxLength outPointer = inPoint + 1.0; delay = length - 1; } else if (theDelay < 0.5) { std::cerr << "[chuck](via STK): DelayA: setDelay(" << theDelay << ") less than 0.5 not possible!" << std::endl; outPointer = inPoint + 0.4999999999; delay = 0.5; } else { outPointer = inPoint - theDelay + 1.0; // outPoint chases inpoint delay = theDelay; } if (outPointer < 0) outPointer += length; // modulo maximum length outPoint = (long) outPointer; // integer part alpha = 1.0 + outPoint - outPointer; // fractional part if (alpha < 0.5) { // The optimal range for alpha is about 0.5 - 1.5 in order to // achieve the flattest phase delay response. outPoint += 1; if (outPoint >= length) outPoint -= length; alpha += (MY_FLOAT) 1.0; } coeff = ((MY_FLOAT) 1.0 - alpha) / ((MY_FLOAT) 1.0 + alpha); // coefficient for all pass } MY_FLOAT DelayA :: nextOut(void) { if ( doNextOut ) { // Do allpass interpolation delay. nextOutput = -coeff * outputs[0]; nextOutput += apInput + (coeff * inputs[outPoint]); doNextOut = false; } return nextOutput; } MY_FLOAT DelayA :: tick(MY_FLOAT sample) { inputs[inPoint++] = sample; // Increment input pointer modulo length. if (inPoint == length) inPoint -= length; outputs[0] = nextOut(); doNextOut = true; // Save the allpass input and increment modulo length. apInput = inputs[outPoint++]; if (outPoint == length) outPoint -= length; return outputs[0]; } /***************************************************/ /*! \class DelayL \brief STK linear interpolating delay line class. This Delay subclass implements a fractional- length digital delay-line using first-order linear interpolation. A fixed maximum length of 4095 and a delay of zero is set using the default constructor. Alternatively, the delay and maximum length can be set during instantiation with an overloaded constructor. Linear interpolation is an efficient technique for achieving fractional delay lengths, though it does introduce high-frequency signal attenuation to varying degrees depending on the fractional delay setting. The use of higher order Lagrange interpolators can typically improve (minimize) this attenuation characteristic. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include DelayL :: DelayL() { doNextOut = true; } DelayL :: DelayL(MY_FLOAT theDelay, long maxDelay) { // Writing before reading allows delays from 0 to length-1. length = maxDelay+1; if ( length > 4096 ) { // We need to delete the previously allocated inputs. delete [] inputs; inputs = new MY_FLOAT[length]; this->clear(); } inPoint = 0; this->setDelay(theDelay); doNextOut = true; } DelayL :: ~DelayL() { } void DelayL :: set( MY_FLOAT delay, long max ) { // Writing before reading allows delays from 0 to length-1. // If we want to allow a delay of maxDelay, we need a // delay-line of length = maxDelay+1. length = max+1; // We need to delete the previously allocated inputs. if( inputs ) delete [] inputs; inputs = new MY_FLOAT[length]; this->clear(); inPoint = 0; this->setDelay(delay); doNextOut = true; } void DelayL :: setDelay(MY_FLOAT theDelay) { MY_FLOAT outPointer; if (theDelay > length-1) { std::cerr << "[chuck](via STK): DelayL: setDelay(" << theDelay << ") too big!" << std::endl; // Force delay to maxLength outPointer = inPoint + 1.0; delay = length - 1; } else if (theDelay < 0 ) { std::cerr << "[chuck](via STK): DelayL: setDelay(" << theDelay << ") less than zero!" << std::endl; outPointer = inPoint; delay = 0; } else { outPointer = inPoint - theDelay; // read chases write delay = theDelay; } while (outPointer < 0) outPointer += length; // modulo maximum length outPoint = (long) outPointer; // integer part alpha = outPointer - outPoint; // fractional part omAlpha = (MY_FLOAT) 1.0 - alpha; } MY_FLOAT DelayL :: nextOut(void) { if ( doNextOut ) { // First 1/2 of interpolation nextOutput = inputs[outPoint] * omAlpha; // Second 1/2 of interpolation if (outPoint+1 < length) nextOutput += inputs[outPoint+1] * alpha; else nextOutput += inputs[0] * alpha; doNextOut = false; } return nextOutput; } MY_FLOAT DelayL :: tick(MY_FLOAT sample) { inputs[inPoint++] = sample; // Increment input pointer modulo length. if (inPoint == length) inPoint -= length; outputs[0] = nextOut(); doNextOut = true; // Increment output pointer modulo length. if (++outPoint >= length) outPoint -= length; return outputs[0]; } /***************************************************/ /*! \class Drummer \brief STK drum sample player class. This class implements a drum sampling synthesizer using WvIn objects and one-pole filters. The drum rawwave files are sampled at 22050 Hz, but will be appropriately interpolated for other sample rates. You can specify the maximum polyphony (maximum number of simultaneous voices) via a #define in the Drummer.h. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include // Not really General MIDI yet. Coming soon. unsigned char genMIDIMap[128] = { 0,0,0,0,0,0,0,0, // 0-7 0,0,0,0,0,0,0,0, // 8-15 0,0,0,0,0,0,0,0, // 16-23 0,0,0,0,0,0,0,0, // 24-31 0,0,0,0,1,0,2,0, // 32-39 2,3,6,3,6,4,7,4, // 40-47 5,8,5,0,0,0,10,0, // 48-55 9,0,0,0,0,0,0,0, // 56-63 0,0,0,0,0,0,0,0, // 64-71 0,0,0,0,0,0,0,0, // 72-79 0,0,0,0,0,0,0,0, // 80-87 0,0,0,0,0,0,0,0, // 88-95 0,0,0,0,0,0,0,0, // 96-103 0,0,0,0,0,0,0,0, // 104-111 0,0,0,0,0,0,0,0, // 112-119 0,0,0,0,0,0,0,0 // 120-127 }; //XXX changed this from 16 to 32 for the 'special' convention..also, we do not have these linked //in the headers char waveNames[DRUM_NUMWAVES][32] = { "special:dope", "special:bassdrum", "special:snardrum", "special:tomlowdr", "special:tommiddr", "special:tomhidrm", "special:hihatcym", "special:ridecymb", "special:crashcym", "special:cowbell1", "special:tambourn" }; Drummer :: Drummer() : Instrmnt() { for (int i=0; i= 0 ) { // Reset this sound. waves[waveIndex]->reset(); filters[waveIndex]->setPole((MY_FLOAT) 0.999 - (gain * 0.6)); filters[waveIndex]->setGain(gain); } else { if (nSounding == DRUM_POLYPHONY) { // If we're already at maximum polyphony, then preempt the oldest voice. delete waves[0]; filters[0]->clear(); WvIn *tempWv = waves[0]; OnePole *tempFilt = filters[0]; // Re-order the list. for (i=0; isetRate( 22050.0 / Stk::sampleRate() ); filters[nSounding-1]->setPole((MY_FLOAT) 0.999 - (gain * 0.6) ); filters[nSounding-1]->setGain( gain ); } #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Number Sounding = " << nSounding << std::endl; for (i=0; isetGain( amplitude * 0.01 ); } } MY_FLOAT Drummer :: tick() { MY_FLOAT output = 0.0; OnePole *tempFilt; int j, i = 0; while (i < nSounding) { if ( waves[i]->isFinished() ) { delete waves[i]; tempFilt = filters[i]; // Re-order the list. for (j=i; jclear(); sounding[j] = -1; nSounding -= 1; i -= 1; } else output += filters[i]->tick( waves[i]->tick() ); i++; } return output; } /***************************************************/ /*! \class Echo \brief STK echo effect class. This class implements a echo effect. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Echo :: Echo(MY_FLOAT longestDelay) { delayLine = NULL; this->set( longestDelay ); effectMix = 0.5; } Echo :: ~Echo() { delete delayLine; } void Echo :: set( MY_FLOAT max ) { length = (long)max + 2; MY_FLOAT delay = delayLine ? delayLine->getDelay() : length>>1; if( delayLine ) delete delayLine; if( delay >= max ) delay = max; delayLine = new Delay(length>>1, length); this->clear(); this->setDelay(delay+.5); } MY_FLOAT Echo :: getDelay() { return delayLine->getDelay(); } void Echo :: clear() { delayLine->clear(); lastOutput = 0.0; } void Echo :: setDelay(MY_FLOAT delay) { MY_FLOAT size = delay; if ( delay < 0.0 ) { std::cerr << "[chuck](via STK): Echo: setDelay parameter is less than zero!" << std::endl; size = 0.0; } else if ( delay > length ) { std::cerr << "[chuck](via STK): Echo: setDelay parameter is greater than delay length!" << std::endl; size = length; } delayLine->setDelay((long)size); } void Echo :: setEffectMix(MY_FLOAT mix) { effectMix = mix; if ( mix < 0.0 ) { std::cerr << "[chuck](via STK): Echo: setEffectMix parameter is less than zero!" << std::endl; effectMix = 0.0; } else if ( mix > 1.0 ) { std::cerr << "[chuck](via STK): Echo: setEffectMix parameter is greater than 1.0!" << std::endl; effectMix = 1.0; } } MY_FLOAT Echo :: lastOut() const { return lastOutput; } MY_FLOAT Echo :: tick(MY_FLOAT input) { lastOutput = effectMix * delayLine->tick(input); lastOutput += input * (1.0 - effectMix); return lastOutput; } MY_FLOAT *Echo :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i Envelope :: Envelope(void) : Stk() { target = (MY_FLOAT) 0.0; value = (MY_FLOAT) 0.0; rate = (MY_FLOAT) 0.001; m_target = 1.0; m_time = rate * Stk::sampleRate(); state = 0; } Envelope :: ~Envelope(void) { } void Envelope :: keyOn(void) { target = (MY_FLOAT) m_target; if (value != target) state = 1; } void Envelope :: keyOff(void) { target = (MY_FLOAT) 0.0; if (value != target) state = 1; } void Envelope :: setRate(MY_FLOAT aRate) { if (aRate < 0.0) { printf("[chuck](via Envelope): negative rates not allowed ... correcting!\n"); rate = -aRate; } else rate = aRate; m_time = m_target / (rate * Stk::sampleRate()); if( m_time < 0.0 ) m_time = -m_time; } void Envelope :: setTime(MY_FLOAT aTime) { if (aTime < 0.0) { printf("[chuck](via Envelope): negative times not allowed ... correcting!\n"); rate = m_target / (-aTime * Stk::sampleRate()); } else if( aTime == 0.0 ) rate = FLT_MAX; else rate = m_target / (aTime * Stk::sampleRate()); m_time = aTime; if( m_time < 0.0 ) m_time = -m_time; } void Envelope :: setTarget(MY_FLOAT aTarget) { target = m_target = aTarget; if (value != target) state = 1; // set time setTime( m_time ); } void Envelope :: setValue(MY_FLOAT aValue) { state = 0; target = aValue; value = aValue; } int Envelope :: getState(void) const { return state; } MY_FLOAT Envelope :: tick(void) { if (state) { if (target > value) { value += rate; if (value >= target) { value = target; state = 0; } } else { value -= rate; if (value <= target) { value = target; state = 0; } } } return value; } MY_FLOAT *Envelope :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i FM :: FM(int operators) : nOperators(operators) { if ( nOperators <= 0 ) { char msg[256]; sprintf(msg, "[chuck](via FM): Invalid number of operators (%d) argument to constructor!", operators); handleError(msg, StkError::FUNCTION_ARGUMENT); } twozero = new TwoZero(); twozero->setB2( -1.0 ); twozero->setGain( 0.0 ); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency(6.0); int i; ratios = (MY_FLOAT *) new MY_FLOAT[nOperators]; gains = (MY_FLOAT *) new MY_FLOAT[nOperators]; adsr = (ADSR **) calloc( nOperators, sizeof(ADSR *) ); waves = (WaveLoop **) calloc( nOperators, sizeof(WaveLoop *) ); for (i=0; i=0; i--) { __FM_gains[i] = temp; temp *= 0.933033; } temp = 1.0; for (i=15; i>=0; i--) { __FM_susLevels[i] = temp; temp *= 0.707101; } temp = 8.498186; for (i=0; i<32; i++) { __FM_attTimes[i] = temp; temp *= 0.707101; } } FM :: ~FM() { delete vibrato; delete twozero; delete [] ratios; delete [] gains; for (int i=0; isetFrequency( baseFrequency * ratios[i] ); // chuck m_frequency = baseFrequency; } void FM :: setRatio(int waveIndex, MY_FLOAT ratio) { if ( waveIndex < 0 ) { std::cerr << "[chuck](via STK): FM: setRatio waveIndex parameter is less than zero!" << std::endl; return; } else if ( waveIndex >= nOperators ) { std::cerr << "[chuck](via STK): FM: setRatio waveIndex parameter is greater than the number of operators!" << std::endl; return; } ratios[waveIndex] = ratio; if (ratio > 0.0) waves[waveIndex]->setFrequency(baseFrequency * ratio); else waves[waveIndex]->setFrequency(ratio); } void FM :: setGain(int waveIndex, MY_FLOAT gain) { if ( waveIndex < 0 ) { std::cerr << "[chuck](via STK): FM: setGain waveIndex parameter is less than zero!" << std::endl; return; } else if ( waveIndex >= nOperators ) { std::cerr << "[chuck](via STK): FM: setGain waveIndex parameter is greater than the number of operators!" << std::endl; return; } gains[waveIndex] = gain; } void FM :: setModulationSpeed(MY_FLOAT mSpeed) { vibrato->setFrequency(mSpeed); } void FM :: setModulationDepth(MY_FLOAT mDepth) { modDepth = mDepth; } void FM :: setControl1(MY_FLOAT cVal) { control1 = cVal * (MY_FLOAT) 2.0; } void FM :: setControl2(MY_FLOAT cVal) { control2 = cVal * (MY_FLOAT) 2.0; } void FM :: keyOn() { for (int i=0; ikeyOn(); } void FM :: keyOff() { for (int i=0; ikeyOff(); } void FM :: noteOff(MY_FLOAT amplitude) { keyOff(); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): FM: NoteOff amplitude = " << amplitude << std::endl; #endif } void FM :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): FM: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): FM: Control value greater than 128.0!" << std::endl; } if (number == __SK_Breath_) // 2 setControl1( norm ); else if (number == __SK_FootControl_) // 4 setControl2( norm ); else if (number == __SK_ModFrequency_) // 11 setModulationSpeed( norm * 12.0); else if (number == __SK_ModWheel_) // 1 setModulationDepth( norm ); else if (number == __SK_AfterTouch_Cont_) { // 128 //adsr[0]->setTarget( norm ); adsr[1]->setTarget( norm ); //adsr[2]->setTarget( norm ); adsr[3]->setTarget( norm ); } else std::cerr << "[chuck](via STK): FM: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): FM: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class FMVoices \brief STK singing FM synthesis instrument. This class implements 3 carriers and a common modulator, also referred to as algorithm 6 of the TX81Z. \code Algorithm 6 is : /->1 -\ 4-|-->2 - +-> Out \->3 -/ \endcode Control Change Numbers: - Vowel = 2 - Spectral Tilt = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ FMVoices :: FMVoices() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 2.00); this->setRatio(1, 4.00); this->setRatio(2, 12.0); this->setRatio(3, 1.00); gains[3] = __FM_gains[80]; adsr[0]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05); adsr[1]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05); adsr[2]->setAllTimes( 0.05, 0.05, __FM_susLevels[15], 0.05); adsr[3]->setAllTimes( 0.01, 0.01, __FM_susLevels[15], 0.5); twozero->setGain( 0.0 ); modDepth = (MY_FLOAT) 0.005; currentVowel = 0; tilt[0] = 1.0; tilt[1] = 0.5; tilt[2] = 0.2; mods[0] = 1.0; mods[1] = 1.1; mods[2] = 1.1; baseFrequency = 110.0; setFrequency( 110.0 ); } FMVoices :: ~FMVoices() { } void FMVoices :: setFrequency(MY_FLOAT frequency) { MY_FLOAT temp, temp2 = 0.0; int tempi = 0; unsigned int i = 0; if (currentVowel < 32) { i = currentVowel; temp2 = (MY_FLOAT) 0.9; } else if (currentVowel < 64) { i = currentVowel - 32; temp2 = (MY_FLOAT) 1.0; } else if (currentVowel < 96) { i = currentVowel - 64; temp2 = (MY_FLOAT) 1.1; } else if (currentVowel <= 128) { i = currentVowel - 96; temp2 = (MY_FLOAT) 1.2; } baseFrequency = frequency; temp = (temp2 * Phonemes::formantFrequency(i, 0) / baseFrequency) + 0.5; tempi = (int) temp; this->setRatio(0,(MY_FLOAT) tempi); temp = (temp2 * Phonemes::formantFrequency(i, 1) / baseFrequency) + 0.5; tempi = (int) temp; this->setRatio(1,(MY_FLOAT) tempi); temp = (temp2 * Phonemes::formantFrequency(i, 2) / baseFrequency) + 0.5; tempi = (int) temp; this->setRatio(2, (MY_FLOAT) tempi); gains[0] = 1.0; gains[1] = 1.0; gains[2] = 1.0; // chuck m_frequency = baseFrequency; } void FMVoices :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); tilt[0] = amplitude; tilt[1] = amplitude * amplitude; tilt[2] = tilt[1] * amplitude; this->keyOn(); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): FMVoices: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } MY_FLOAT FMVoices :: tick() { register MY_FLOAT temp, temp2; temp = gains[3] * adsr[3]->tick() * waves[3]->tick(); temp2 = vibrato->tick() * modDepth * (MY_FLOAT) 0.1; waves[0]->setFrequency(baseFrequency * (1.0 + temp2) * ratios[0]); waves[1]->setFrequency(baseFrequency * (1.0 + temp2) * ratios[1]); waves[2]->setFrequency(baseFrequency * (1.0 + temp2) * ratios[2]); waves[3]->setFrequency(baseFrequency * (1.0 + temp2) * ratios[3]); waves[0]->addPhaseOffset(temp * mods[0]); waves[1]->addPhaseOffset(temp * mods[1]); waves[2]->addPhaseOffset(temp * mods[2]); waves[3]->addPhaseOffset(twozero->lastOut()); twozero->tick(temp); temp = gains[0] * tilt[0] * adsr[0]->tick() * waves[0]->tick(); temp += gains[1] * tilt[1] * adsr[1]->tick() * waves[1]->tick(); temp += gains[2] * tilt[2] * adsr[2]->tick() * waves[2]->tick(); return temp * 0.33; } void FMVoices :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): FMVoices: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): FMVoices: Control value greater than 128.0!" << std::endl; } if (number == __SK_Breath_) // 2 gains[3] = __FM_gains[(int) ( norm * 99.9 )]; else if (number == __SK_FootControl_) { // 4 currentVowel = (int) (norm * 128.0); this->setFrequency(baseFrequency); } else if (number == __SK_ModFrequency_) // 11 this->setModulationSpeed( norm * 12.0); else if (number == __SK_ModWheel_) // 1 this->setModulationDepth( norm ); else if (number == __SK_AfterTouch_Cont_) { // 128 tilt[0] = norm; tilt[1] = norm * norm; tilt[2] = tilt[1] * norm; } else std::cerr << "[chuck](via STK): FMVoices: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): FMVoices: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Filter \brief STK filter class. This class implements a generic structure which can be used to create a wide range of filters. It can function independently or be subclassed to provide more specific controls based on a particular filter type. In particular, this class implements the standard difference equation: a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] - a[1]*y[n-1] - ... - a[na]*y[n-na] If a[0] is not equal to 1, the filter coeffcients are normalized by a[0]. The \e gain parameter is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. This structure results in one extra multiply per computed sample, but allows easy control of the overall filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include FilterStk :: FilterStk() { // The default constructor should setup for pass-through. gain = 1.0; nB = 1; nA = 1; b = new MY_FLOAT[nB]; b[0] = 1.0; a = new MY_FLOAT[nA]; a[0] = 1.0; inputs = new MY_FLOAT[nB]; outputs = new MY_FLOAT[nA]; this->clear(); } FilterStk :: FilterStk(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients) { char message[256]; // Check the arguments. if ( nb < 1 || na < 1 ) { sprintf(message, "[chuck](via Filter): nb (%d) and na (%d) must be >= 1!", nb, na); handleError( message, StkError::FUNCTION_ARGUMENT ); } if ( aCoefficients[0] == 0.0 ) { sprintf(message, "[chuck](via Filter): a[0] coefficient cannot == 0!"); handleError( message, StkError::FUNCTION_ARGUMENT ); } gain = 1.0; nB = nb; nA = na; b = new MY_FLOAT[nB]; a = new MY_FLOAT[nA]; inputs = new MY_FLOAT[nB]; outputs = new MY_FLOAT[nA]; this->clear(); this->setCoefficients(nB, bCoefficients, nA, aCoefficients); } FilterStk :: ~FilterStk() { delete [] b; delete [] a; delete [] inputs; delete [] outputs; } void FilterStk :: clear(void) { int i; for (i=0; i= 1!", nb, na); handleError( message, StkError::FUNCTION_ARGUMENT ); } if ( aCoefficients[0] == 0.0 ) { sprintf(message, "[chuck](via Filter): a[0] coefficient cannot == 0!"); handleError( message, StkError::FUNCTION_ARGUMENT ); } if (nb != nB) { delete [] b; delete [] inputs; nB = nb; b = new MY_FLOAT[nB]; inputs = new MY_FLOAT[nB]; for (i=0; i= 1!", nb); handleError( message, StkError::FUNCTION_ARGUMENT ); } if (nb != nB) { delete [] b; delete [] inputs; nB = nb; b = new MY_FLOAT[nB]; inputs = new MY_FLOAT[nB]; for (i=0; i= 1!", na); handleError( message, StkError::FUNCTION_ARGUMENT ); } if ( aCoefficients[0] == 0.0 ) { sprintf(message, "[chuck](via Filter): a[0] coefficient cannot == 0!"); handleError( message, StkError::FUNCTION_ARGUMENT ); } if (na != nA) { delete [] a; delete [] outputs; nA = na; a = new MY_FLOAT[nA]; outputs = new MY_FLOAT[nA]; for (i=0; i0; i--) { outputs[0] += b[i] * inputs[i]; inputs[i] = inputs[i-1]; } outputs[0] += b[0] * inputs[0]; for (i=nA-1; i>0; i--) { outputs[0] += -a[i] * outputs[i]; outputs[i] = outputs[i-1]; } return outputs[0]; } MY_FLOAT *FilterStk :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i>= 1; jetDelay = new DelayL( 49.0, length ); jetTable = new JetTabl(); filter = new OnePole(); dcBlock = new PoleZero(); dcBlock->setBlockZero(); noise = new Noise(); adsr = new ADSR(); // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency( 5.925 ); this->clear(); filter->setPole( 0.7 - ((MY_FLOAT) 0.1 * 22050.0 / Stk::sampleRate() ) ); filter->setGain( -1.0 ); adsr->setAllTimes( 0.005, 0.01, 0.8, 0.010); endReflection = (MY_FLOAT) 0.5; jetReflection = (MY_FLOAT) 0.5; noiseGain = 0.15; // Breath pressure random component. vibratoGain = (MY_FLOAT) 0.05; // Breath periodic vibrato component. jetRatio = (MY_FLOAT) 0.32; maxPressure = (MY_FLOAT) 0.0; lastFrequency = 220.0; // CHUCK //reverse: nothing m_frequency = lastFrequency; //reverse: nothing (see setJetDelay) m_jetDelay = jetRatio; //reverse: nothing m_jetReflection = jetReflection; //reverse: nothing m_endReflection = endReflection; //reverse: noiseGain = norm * 0.4 m_noiseGain = noiseGain / .4; //reverse: same * 12.0 m_vibratoFreq = vibrato->m_freq / 12.0; //reverse: same * 0.4 m_vibratoGain = .15 / 0.4; //reverse: nothing m_pressure = 1.0; //reverse: nothing m_rate = .005; } Flute :: ~Flute() { delete jetDelay; delete boreDelay; delete jetTable; delete filter; delete dcBlock; delete noise; delete adsr; delete vibrato; } void Flute :: clear() { jetDelay->clear(); boreDelay->clear(); filter->clear(); dcBlock->clear(); } void Flute :: setFrequency(MY_FLOAT frequency) { lastFrequency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Flute: setFrequency parameter is less than or equal to zero!" << std::endl; lastFrequency = 220.0; } // We're overblowing here. lastFrequency *= 0.66666; // Delay = length - approximate filter delay. MY_FLOAT delay = Stk::sampleRate() / lastFrequency - (MY_FLOAT) 2.0; if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; boreDelay->setDelay(delay); jetDelay->setDelay(delay * jetRatio); // chuck m_frequency = frequency; } void Flute :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Flute: startblowing " << amplitude << " " << rate << endl; #endif adsr->setAttackRate(rate); maxPressure = amplitude / (MY_FLOAT) 0.8; adsr->keyOn(); } void Flute :: stopBlowing(MY_FLOAT rate) { adsr->setReleaseRate(rate); adsr->keyOff(); } void Flute :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); startBlowing( 1.1 + (amplitude * 0.20), amplitude * 0.02); outputGain = amplitude + 0.001; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Flute: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Flute :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.02); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Flute: NoteOff amplitude = " << amplitude << std::endl; #endif } void Flute :: setJetReflection(MY_FLOAT coefficient) { jetReflection = coefficient; m_jetReflection = coefficient; } void Flute :: setEndReflection(MY_FLOAT coefficient) { endReflection = coefficient; m_endReflection = coefficient; } void Flute :: setJetDelay(MY_FLOAT aRatio) { // Delay = length - approximate filter delay. MY_FLOAT temp = Stk::sampleRate() / lastFrequency - (MY_FLOAT) 2.0; jetRatio = aRatio; jetDelay->setDelay(temp * aRatio); // Scaled by ratio. m_jetDelay = aRatio; } MY_FLOAT Flute :: tick() { MY_FLOAT pressureDiff; MY_FLOAT breathPressure; // Calculate the breath pressure (envelope + noise + vibrato) breathPressure = maxPressure * adsr->tick(); breathPressure += breathPressure * noiseGain * noise->tick(); breathPressure += breathPressure * vibratoGain * vibrato->tick(); MY_FLOAT temp = filter->tick( boreDelay->lastOut() ); temp = dcBlock->tick(temp); // Block DC on reflection. pressureDiff = breathPressure - (jetReflection * temp); pressureDiff = jetDelay->tick( pressureDiff ); pressureDiff = jetTable->tick( pressureDiff ) + (endReflection * temp); lastOutput = (MY_FLOAT) 0.3 * boreDelay->tick( pressureDiff ); lastOutput *= outputGain; return lastOutput; } void Flute :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Flute: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Flute: Control value greater than 128.0!" << std::endl; } if (number == __SK_JetDelay_) // 2 this->setJetDelay( (MY_FLOAT) (0.08 + (0.48 * norm)) ); else if (number == __SK_NoiseLevel_) { // 4 m_noiseGain = norm; noiseGain = ( norm * 0.4); } else if (number == __SK_ModFrequency_) // 11 setVibratoFreq( norm * 12.0 ); else if (number == __SK_ModWheel_) { // 1 m_vibratoGain = norm; vibratoGain = ( norm * 0.4 ); } else if (number == __SK_AfterTouch_Cont_) { // 128 m_pressure = norm; adsr->setTarget( norm ); } else std::cerr << "[chuck](via STK): Flute: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Flute: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class FormSwep \brief STK sweepable formant filter class. This public BiQuad filter subclass implements a formant (resonance) which can be "swept" over time from one frequency setting to another. It provides methods for controlling the sweep rate and target frequency. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ FormSwep :: FormSwep() : BiQuad() { frequency = (MY_FLOAT) 0.0; radius = (MY_FLOAT) 0.0; targetGain = (MY_FLOAT) 1.0; targetFrequency = (MY_FLOAT) 0.0; targetRadius = (MY_FLOAT) 0.0; deltaGain = (MY_FLOAT) 0.0; deltaFrequency = (MY_FLOAT) 0.0; deltaRadius = (MY_FLOAT) 0.0; sweepState = (MY_FLOAT) 0.0; sweepRate = (MY_FLOAT) 0.002; dirty = false; this->clear(); } FormSwep :: ~FormSwep() { } void FormSwep :: setResonance(MY_FLOAT aFrequency, MY_FLOAT aRadius) { dirty = false; radius = aRadius; frequency = aFrequency; BiQuad::setResonance( frequency, radius, true ); } void FormSwep :: setStates(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain) { dirty = false; if ( frequency != aFrequency || radius != aRadius ) BiQuad::setResonance( aFrequency, aRadius, true ); frequency = aFrequency; radius = aRadius; gain = aGain; targetFrequency = aFrequency; targetRadius = aRadius; targetGain = aGain; } void FormSwep :: setTargets(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain) { dirty = true; startFrequency = frequency; startRadius = radius; startGain = gain; targetFrequency = aFrequency; targetRadius = aRadius; targetGain = aGain; deltaFrequency = aFrequency - frequency; deltaRadius = aRadius - radius; deltaGain = aGain - gain; sweepState = (MY_FLOAT) 0.0; } void FormSwep :: setSweepRate(MY_FLOAT aRate) { sweepRate = aRate; if ( sweepRate > 1.0 ) sweepRate = 1.0; if ( sweepRate < 0.0 ) sweepRate = 0.0; } void FormSwep :: setSweepTime(MY_FLOAT aTime) { sweepRate = 1.0 / ( aTime * Stk::sampleRate() ); if ( sweepRate > 1.0 ) sweepRate = 1.0; if ( sweepRate < 0.0 ) sweepRate = 0.0; } MY_FLOAT FormSwep :: tick(MY_FLOAT sample) { if (dirty) { sweepState += sweepRate; if ( sweepState >= 1.0 ) { sweepState = (MY_FLOAT) 1.0; dirty = false; radius = targetRadius; frequency = targetFrequency; gain = targetGain; } else { radius = startRadius + (deltaRadius * sweepState); frequency = startFrequency + (deltaFrequency * sweepState); gain = startGain + (deltaGain * sweepState); } BiQuad::setResonance( frequency, radius, true ); } return BiQuad::tick( sample ); } MY_FLOAT *FormSwep :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i2-- + -->1-->Out Control Change Numbers: - Total Modulator Index = 2 - Modulator Crossfade = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ HevyMetl :: HevyMetl() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 1.0 * 1.000); this->setRatio(1, 4.0 * 0.999); this->setRatio(2, 3.0 * 1.001); this->setRatio(3, 0.5 * 1.002); gains[0] = __FM_gains[92]; gains[1] = __FM_gains[76]; gains[2] = __FM_gains[91]; gains[3] = __FM_gains[68]; adsr[0]->setAllTimes( 0.001, 0.001, 1.0, 0.01); adsr[1]->setAllTimes( 0.001, 0.010, 1.0, 0.50); adsr[2]->setAllTimes( 0.010, 0.005, 1.0, 0.20); adsr[3]->setAllTimes( 0.030, 0.010, 0.2, 0.20); twozero->setGain( 2.0 ); vibrato->setFrequency( 5.5 ); modDepth = 0.0; } HevyMetl :: ~HevyMetl() { } void HevyMetl :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[92]; gains[1] = amplitude * __FM_gains[76]; gains[2] = amplitude * __FM_gains[91]; gains[3] = amplitude * __FM_gains[68]; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "HevyMetl: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT HevyMetl :: tick() { register MY_FLOAT temp; temp = vibrato->tick() * modDepth * 0.2; waves[0]->setFrequency(baseFrequency * (1.0 + temp) * ratios[0]); waves[1]->setFrequency(baseFrequency * (1.0 + temp) * ratios[1]); waves[2]->setFrequency(baseFrequency * (1.0 + temp) * ratios[2]); waves[3]->setFrequency(baseFrequency * (1.0 + temp) * ratios[3]); temp = gains[2] * adsr[2]->tick() * waves[2]->tick(); waves[1]->addPhaseOffset(temp); waves[3]->addPhaseOffset(twozero->lastOut()); temp = (1.0 - (control2 * 0.5)) * gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); temp += control2 * (MY_FLOAT) 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick(); temp = temp * control1; waves[0]->addPhaseOffset(temp); temp = gains[0] * adsr[0]->tick() * waves[0]->tick(); lastOutput = temp * 0.5; return lastOutput; } /***************************************************/ /*! \class Instrmnt \brief STK instrument abstract base class. This class provides a common interface for all STK instruments. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Instrmnt :: Instrmnt() { m_frequency = 0; } Instrmnt :: ~Instrmnt() { } void Instrmnt :: setFrequency(MY_FLOAT frequency) { std::cerr << "[chuck](via STK): Instrmnt: virtual setFrequency function call!" << std::endl; // m_frequency = frequency; } MY_FLOAT Instrmnt :: lastOut() const { return lastOutput; } // Support for stereo output: MY_FLOAT Instrmnt :: lastOutLeft(void) const { return 0.5 * lastOutput; } MY_FLOAT Instrmnt :: lastOutRight(void) const { return 0.5 * lastOutput; } MY_FLOAT *Instrmnt :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i JCRev :: JCRev(MY_FLOAT T60) { // Delay lengths for 44100 Hz sample rate. int lengths[9] = {1777, 1847, 1993, 2137, 389, 127, 43, 211, 179}; double scaler = Stk::sampleRate() / 44100.0; int delay, i; if ( scaler != 1.0 ) { for (i=0; i<9; i++) { delay = (int) floor(scaler * lengths[i]); if ( (delay & 1) == 0) delay++; while ( !this->isPrime(delay) ) delay += 2; lengths[i] = delay; } } for (i=0; i<3; i++) allpassDelays[i] = new Delay(lengths[i+4], lengths[i+4]); for (i=0; i<4; i++) { combDelays[i] = new Delay(lengths[i], lengths[i]); combCoefficient[i] = pow(10.0,(-3 * lengths[i] / (T60 * Stk::sampleRate()))); } outLeftDelay = new Delay(lengths[7], lengths[7]); outRightDelay = new Delay(lengths[8], lengths[8]); allpassCoefficient = 0.7; effectMix = 0.3; this->clear(); } JCRev :: ~JCRev() { delete allpassDelays[0]; delete allpassDelays[1]; delete allpassDelays[2]; delete combDelays[0]; delete combDelays[1]; delete combDelays[2]; delete combDelays[3]; delete outLeftDelay; delete outRightDelay; } void JCRev :: clear() { allpassDelays[0]->clear(); allpassDelays[1]->clear(); allpassDelays[2]->clear(); combDelays[0]->clear(); combDelays[1]->clear(); combDelays[2]->clear(); combDelays[3]->clear(); outRightDelay->clear(); outLeftDelay->clear(); lastOutput[0] = 0.0; lastOutput[1] = 0.0; } MY_FLOAT JCRev :: tick(MY_FLOAT input) { MY_FLOAT temp, temp0, temp1, temp2, temp3, temp4, temp5, temp6; MY_FLOAT filtout; // gewang: dedenormal CK_STK_DDN(input); temp = allpassDelays[0]->lastOut(); temp0 = allpassCoefficient * temp; temp0 += input; // gewang: dedenormal CK_STK_DDN(temp0); allpassDelays[0]->tick(temp0); temp0 = -(allpassCoefficient * temp0) + temp; temp = allpassDelays[1]->lastOut(); temp1 = allpassCoefficient * temp; temp1 += temp0; // gewang: dedenormal CK_STK_DDN(temp1); allpassDelays[1]->tick(temp1); temp1 = -(allpassCoefficient * temp1) + temp; temp = allpassDelays[2]->lastOut(); temp2 = allpassCoefficient * temp; temp2 += temp1; // gewang: dedenormal CK_STK_DDN(temp2); allpassDelays[2]->tick(temp2); temp2 = -(allpassCoefficient * temp2) + temp; temp3 = temp2 + (combCoefficient[0] * combDelays[0]->lastOut()); temp4 = temp2 + (combCoefficient[1] * combDelays[1]->lastOut()); temp5 = temp2 + (combCoefficient[2] * combDelays[2]->lastOut()); temp6 = temp2 + (combCoefficient[3] * combDelays[3]->lastOut()); // gewang: dedenormal CK_STK_DDN(temp3); CK_STK_DDN(temp4); CK_STK_DDN(temp5); CK_STK_DDN(temp6); combDelays[0]->tick(temp3); combDelays[1]->tick(temp4); combDelays[2]->tick(temp5); combDelays[3]->tick(temp6); filtout = temp3 + temp4 + temp5 + temp6; // gewang: dedenormal CK_STK_DDN(filtout); lastOutput[0] = effectMix * (outLeftDelay->tick(filtout)); lastOutput[1] = effectMix * (outRightDelay->tick(filtout)); temp = (1.0 - effectMix) * input; lastOutput[0] += temp; lastOutput[1] += temp; return (lastOutput[0] + lastOutput[1]) * 0.5; } /***************************************************/ /*! \class JetTabl \brief STK jet table class. This class implements a flue jet non-linear function, computed by a polynomial calculation. Contrary to the name, this is not a "table". Consult Fletcher and Rossing, Karjalainen, Cook, and others for more information. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ JetTabl :: JetTabl() { lastOutput = (MY_FLOAT) 0.0; } JetTabl :: ~JetTabl() { } MY_FLOAT JetTabl :: lastOut() const { return lastOutput; } MY_FLOAT JetTabl :: tick( MY_FLOAT input ) { // Perform "table lookup" using a polynomial // calculation (x^3 - x), which approximates // the jet sigmoid behavior. lastOutput = input * (input * input - (MY_FLOAT) 1.0); // Saturate at +/- 1.0. if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0; if (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0; return lastOutput; } MY_FLOAT *JetTabl :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; iisFinished(); //reverse: nothing m_bodySize = 1.0; } bool Mandolin :: setBodyIR( const char * path, bool isRaw ) { soundfile[0]->openFile( path, isRaw ); return true; } Mandolin :: ~Mandolin() { for( int i=0; i<12; i++ ) SAFE_DELETE( soundfile[i] ); } void Mandolin :: pluck(MY_FLOAT amplitude) { // This function gets interesting, because pluck // may be longer than string length, so we just // reset the soundfile and add in the pluck in // the tick method. soundfile[mic]->reset(); waveDone = false; pluckAmplitude = amplitude; if ( amplitude < 0.0 ) { std::cerr << "[chuck](via STK): Mandolin: pluck amplitude parameter less than zero!" << std::endl; pluckAmplitude = 0.0; } else if ( amplitude > 1.0 ) { std::cerr << "[chuck](via STK): Mandolin: pluck amplitude parameter greater than 1.0!" << std::endl; pluckAmplitude = 1.0; } // Set the pick position, which puts zeroes at position * length. combDelay->setDelay((MY_FLOAT) 0.5 * pluckPosition * lastLength); dampTime = (long) lastLength; // See tick method below. } void Mandolin :: pluck(MY_FLOAT amplitude, MY_FLOAT position) { // Pluck position puts zeroes at position * length. pluckPosition = position; if ( position < 0.0 ) { std::cerr << "[chuck](via STK): Mandolin: pluck position parameter less than zero!" << std::endl; pluckPosition = 0.0; } else if ( position > 1.0 ) { std::cerr << "[chuck](via STK): Mandolin: pluck position parameter greater than 1.0!" << std::endl; pluckPosition = 1.0; } this->pluck(amplitude); } void Mandolin :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); this->pluck(amplitude); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Mandolin: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Mandolin :: setBodySize(MY_FLOAT size) { m_bodySize = size; // Scale the commuted body response by its sample rate (22050). MY_FLOAT rate = size * soundfile[mic]->sampleRate() / Stk::sampleRate(); for ( int i=0; i<12; i++ ) soundfile[i]->setRate(rate); } MY_FLOAT Mandolin :: tick() { MY_FLOAT temp = 0.0; if ( !waveDone ) { // Scale the pluck excitation with comb // filtering for the duration of the file. temp = soundfile[mic]->tick() * pluckAmplitude; temp = temp - combDelay->tick(temp); waveDone = soundfile[mic]->isFinished(); } // Damping hack to help avoid overflow on re-plucking. if ( dampTime >=0 ) { dampTime -= 1; // Calculate 1st delay filtered reflection plus pluck excitation. lastOutput = delayLine->tick( filter->tick( temp + (delayLine->lastOut() * (MY_FLOAT) 0.7) ) ); // Calculate 2nd delay just like the 1st. lastOutput += delayLine2->tick( filter2->tick( temp + (delayLine2->lastOut() * (MY_FLOAT) 0.7) ) ); } else { // No damping hack after 1 period. // Calculate 1st delay filtered reflection plus pluck excitation. lastOutput = delayLine->tick( filter->tick( temp + (delayLine->lastOut() * loopGain) ) ); // Calculate 2nd delay just like the 1st. lastOutput += delayLine2->tick( filter2->tick( temp + (delayLine2->lastOut() * loopGain) ) ); } lastOutput *= (MY_FLOAT) 0.3; return lastOutput; } void Mandolin :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Mandolin: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Mandolin: Control value greater than 128.0!" << std::endl; } if (number == __SK_BodySize_) // 2 this->setBodySize( norm * 2.0 ); else if (number == __SK_PickPosition_) // 4 this->setPluckPosition( norm ); else if (number == __SK_StringDamping_) // 11 this->setBaseLoopGain((MY_FLOAT) 0.97 + (norm * (MY_FLOAT) 0.03)); else if (number == __SK_StringDetune_) // 1 this->setDetune((MY_FLOAT) 1.0 - (norm * (MY_FLOAT) 0.1)); else if (number == __SK_AfterTouch_Cont_) // 128 mic = (int) (norm * 11.0); else std::cerr << "[chuck](via STK): Mandolin: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Mandolin: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Mesh2D \brief Two-dimensional rectilinear waveguide mesh class. This class implements a rectilinear, two-dimensional digital waveguide mesh structure. For details, see Van Duyne and Smith, "Physical Modeling with the 2-D Digital Waveguide Mesh", Proceedings of the 1993 International Computer Music Conference. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - X Dimension = 2 - Y Dimension = 4 - Mesh Decay = 11 - X-Y Input Position = 1 by Julius Smith, 2000 - 2002. Revised by Gary Scavone for STK, 2002. */ /***************************************************/ #include Mesh2D :: Mesh2D(short nX, short nY) { this->setNX(nX); this->setNY(nY); MY_FLOAT pole = 0.05; short i; for (i=0; isetGain(0.99); } for (i=0; isetGain(0.99); } this->clearMesh(); counter=0; xInput = 0; yInput = 0; } Mesh2D :: ~Mesh2D() { short i; for (i=0; iclearMesh(); short i; for (i=0; iclear(); for (i=0; iclear(); counter=0; } void Mesh2D :: clearMesh() { int x, y; for (x=0; x NXMAX ) { std::cerr << "[chuck](via STK): Mesh2D::setNX(" << lenX << "): Maximum length is " << NXMAX << "!" << std::endl; NX = NXMAX; } } void Mesh2D :: setNY(short lenY) { NY = lenY; if ( lenY < 2 ) { std::cerr << "[chuck](via STK): Mesh2D::setNY(" << lenY << "): Minimum length is 2!" << std::endl; NY = 2; } else if ( lenY > NYMAX ) { std::cerr << "[chuck](via STK): Mesh2D::setNY(" << lenY << "): Maximum length is " << NYMAX << "!" << std::endl; NY = NYMAX; } } void Mesh2D :: setDecay(MY_FLOAT decayFactor) { MY_FLOAT gain = decayFactor; if ( decayFactor < 0.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setDecay decayFactor value is less than 0.0!" << std::endl; gain = 0.0; } else if ( decayFactor > 1.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setDecay decayFactor value is greater than 1.0!" << std::endl; gain = 1.0; } int i; for (i=0; isetGain(gain); for (i=0; isetGain(gain); } void Mesh2D :: setInputPosition(MY_FLOAT xFactor, MY_FLOAT yFactor) { if ( xFactor < 0.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setInputPosition xFactor value is less than 0.0!" << std::endl; xInput = 0; } else if ( xFactor > 1.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setInputPosition xFactor value is greater than 1.0!" << std::endl; xInput = NX - 1; } else xInput = (short) (xFactor * (NX - 1)); if ( yFactor < 0.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setInputPosition yFactor value is less than 0.0!" << std::endl; yInput = 0; } else if ( yFactor > 1.0 ) { std::cerr << "[chuck](via STK): Mesh2D::setInputPosition yFactor value is greater than 1.0!" << std::endl; yInput = NY - 1; } else yInput = (short) (yFactor * (NY - 1)); } void Mesh2D :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { // Input at corner. if ( counter & 1 ) { vxp1[xInput][yInput] += amplitude; vyp1[xInput][yInput] += amplitude; } else { vxp[xInput][yInput] += amplitude; vyp[xInput][yInput] += amplitude; } #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Mesh2D: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Mesh2D :: noteOff(MY_FLOAT amplitude) { #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Mesh2D: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Mesh2D :: tick(MY_FLOAT input) { if ( counter & 1 ) { vxp1[xInput][yInput] += input; vyp1[xInput][yInput] += input; lastOutput = tick1(); } else { vxp[xInput][yInput] += input; vyp[xInput][yInput] += input; lastOutput = tick0(); } counter++; return lastOutput; } MY_FLOAT Mesh2D :: tick() { lastOutput = ((counter & 1) ? this->tick1() : this->tick0()); counter++; return lastOutput; } #define VSCALE ((MY_FLOAT) (0.5)) MY_FLOAT Mesh2D :: tick0() { int x, y; MY_FLOAT outsamp = 0; // Update junction velocities. for (x=0; xtick(vxm[0][y]); vxm1[NX-1][y] = vxp[NX-1][y]; } for (x=0; xtick(vym[x][0]); vym1[x][NY-1] = vyp[x][NY-1]; } // Output = sum of outgoing waves at far corner. Note that the last // index in each coordinate direction is used only with the other // coordinate indices at their next-to-last values. This is because // the "unit strings" attached to each velocity node to terminate // the mesh are not themselves connected together. outsamp = vxp[NX-1][NY-2] + vyp[NX-2][NY-1]; return outsamp; } MY_FLOAT Mesh2D :: tick1() { int x, y; MY_FLOAT outsamp = 0; // Update junction velocities. for (x=0; xtick(vxm1[0][y]); vxm[NX-1][y] = vxp1[NX-1][y]; } for (x=0; xtick(vym1[x][0]); vym[x][NY-1] = vyp1[x][NY-1]; } // Output = sum of outgoing waves at far corner. outsamp = vxp1[NX-1][NY-2] + vyp1[NX-2][NY-1]; return outsamp; } void Mesh2D :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Mesh2D: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Mesh2D: Control value greater than 128.0!" << std::endl; } if (number == 2) // 2 setNX( (short) (norm * (NXMAX-2) + 2) ); else if (number == 4) // 4 setNY( (short) (norm * (NYMAX-2) + 2) ); else if (number == 11) // 11 setDecay( 0.9 + (norm * 0.1) ); else if (number == __SK_ModWheel_) // 1 setInputPosition(norm, norm); else if (number == __SK_AfterTouch_Cont_) // 128 ; else std::cerr << "[chuck](via STK): Mesh2D: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Mesh2D: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Modal \brief STK resonance model instrument. This class contains an excitation wavetable, an envelope, an oscillator, and N resonances (non-sweeping BiQuad filters), where N is set during instantiation. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Modal :: Modal(int modes) : nModes(modes) { if ( nModes <= 0 ) { char msg[256]; sprintf(msg, "[chuck](via Modal): Invalid number of modes (%d) argument to constructor!", modes); handleError(msg, StkError::FUNCTION_ARGUMENT); } // We don't make the excitation wave here yet, because we don't know // what it's going to be. ratios = (MY_FLOAT *) new MY_FLOAT[nModes]; radii = (MY_FLOAT *) new MY_FLOAT[nModes]; filters = (BiQuad **) calloc( nModes, sizeof(BiQuad *) ); for (int i=0; isetEqualGainZeroes(); } envelope = new Envelope; onepole = new OnePole; // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); // Set some default values. vibrato->setFrequency( 6.0 ); vibratoGain = 0.0; directGain = 0.0; masterGain = 1.0; baseFrequency = 440.0; this->clear(); stickHardness = 0.5; strikePosition = 0.561; // chuck m_frequency = baseFrequency; m_vibratoGain = vibratoGain; m_vibratoFreq = vibrato->m_freq; m_volume = 1.0; } Modal :: ~Modal() { delete envelope; delete onepole; delete vibrato; delete [] ratios; delete [] radii; for (int i=0; iclear(); for (int i=0; iclear(); } void Modal :: setFrequency(MY_FLOAT frequency) { baseFrequency = frequency; for (int i=0; isetRatioAndRadius(i, ratios[i], radii[i]); // chuck m_frequency = baseFrequency; } void Modal :: setRatioAndRadius(int modeIndex, MY_FLOAT ratio, MY_FLOAT radius) { if ( modeIndex < 0 ) { std::cerr << "[chuck](via STK): Modal: setRatioAndRadius modeIndex parameter is less than zero!" << std::endl; return; } else if ( modeIndex >= nModes ) { std::cerr << "[chuck](via STK): Modal: setRatioAndRadius modeIndex parameter is greater than the number of operators!" << std::endl; return; } MY_FLOAT nyquist = Stk::sampleRate() / 2.0; MY_FLOAT temp; if (ratio * baseFrequency < nyquist) { ratios[modeIndex] = ratio; } else { temp = ratio; while (temp * baseFrequency > nyquist) temp *= (MY_FLOAT) 0.5; ratios[modeIndex] = temp; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Modal : Aliasing would occur here ... correcting." << std::endl; #endif } radii[modeIndex] = radius; if (ratio < 0) temp = -ratio; else temp = ratio*baseFrequency; filters[modeIndex]->setResonance(temp, radius); } void Modal :: setMasterGain(MY_FLOAT aGain) { masterGain = aGain; } void Modal :: setDirectGain(MY_FLOAT aGain) { directGain = aGain; } void Modal :: setModeGain(int modeIndex, MY_FLOAT gain) { if ( modeIndex < 0 ) { std::cerr << "[chuck](via STK): Modal: setModeGain modeIndex parameter is less than zero!" << std::endl; return; } else if ( modeIndex >= nModes ) { std::cerr << "[chuck](via STK): Modal: setModeGain modeIndex parameter is greater than the number of operators!" << std::endl; return; } filters[modeIndex]->setGain(gain); } void Modal :: strike(MY_FLOAT amplitude) { MY_FLOAT gain = amplitude; if ( amplitude < 0.0 ) { std::cerr << "[chuck](via STK): Modal: strike amplitude is less than zero!" << std::endl; gain = 0.0; } else if ( amplitude > 1.0 ) { std::cerr << "[chuck](via STK): Modal: strike amplitude is greater than 1.0!" << std::endl; gain = 1.0; } envelope->setRate(1.0); envelope->setTarget(gain); onepole->setPole(1.0 - gain); envelope->tick(); wave->reset(); MY_FLOAT temp; for (int i=0; isetResonance(temp, radii[i]); } } void Modal :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); this->strike(amplitude); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Modal: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Modal :: noteOff(MY_FLOAT amplitude) { // This calls damp, but inverts the meaning of amplitude (high // amplitude means fast damping). this->damp(1.0 - (amplitude * 0.03)); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Modal: NoteOff amplitude = " << amplitude << std::endl; #endif } void Modal :: damp(MY_FLOAT amplitude) { MY_FLOAT temp; for (int i=0; isetResonance(temp, radii[i]*amplitude); } } MY_FLOAT Modal :: tick() { MY_FLOAT temp = masterGain * onepole->tick(wave->tick() * envelope->tick()); MY_FLOAT temp2 = 0.0; for (int i=0; itick(temp); temp2 -= temp2 * directGain; temp2 += directGain * temp; if (vibratoGain != 0.0) { // Calculate AM and apply to master out temp = 1.0 + (vibrato->tick() * vibratoGain); temp2 = temp * temp2; } lastOutput = temp2; return lastOutput; } /***************************************************/ /*! \class ModalBar \brief STK resonant bar instrument class. This class implements a number of different struck bar instruments. It inherits from the Modal class. Control Change Numbers: - Stick Hardness = 2 - Stick Position = 4 - Vibrato Gain = 11 - Vibrato Frequency = 7 - Direct Stick Mix = 1 - Volume = 128 - Modal Presets = 16 - Marimba = 0 - Vibraphone = 1 - Agogo = 2 - Wood1 = 3 - Reso = 4 - Wood2 = 5 - Beats = 6 - Two Fixed = 7 - Clump = 8 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include ModalBar :: ModalBar() : Modal() { // Concatenate the STK rawwave path to the rawwave file wave = new WvIn( "special:marmstk1", TRUE ); wave->setRate((MY_FLOAT) 0.5 * 22050.0 / Stk::sampleRate() ); // Set the resonances for preset 0 (marimba). setPreset( 0 ); // chuck m_frequency = baseFrequency; //reverse: same as before m_vibratoGain = vibratoGain / 0.3; //reverse: same as before m_vibratoFreq = vibrato->m_freq / 12.0; m_volume = 1.0; } ModalBar :: ~ModalBar() { delete wave; } void ModalBar :: setStickHardness(MY_FLOAT hardness) { stickHardness = hardness; if ( hardness < 0.0 ) { std::cerr << "[chuck](via STK): ModalBar: setStickHardness parameter is less than zero!" << std::endl; stickHardness = 0.0; } else if ( hardness > 1.0 ) { std::cerr << "[chuck](via STK): ModalBar: setStickHarness parameter is greater than 1.0!" << std::endl; stickHardness = 1.0; } wave->setRate( (0.25 * (MY_FLOAT)pow(4.0, stickHardness)) ); masterGain = 0.1 + (1.8 * stickHardness); } void ModalBar :: setStrikePosition(MY_FLOAT position) { strikePosition = position; if ( position < 0.0 ) { std::cerr << "[chuck](via STK): ModalBar: setStrikePositions parameter is less than zero!" << std::endl; strikePosition = 0.0; } else if ( position > 1.0 ) { std::cerr << "[chuck](via STK): ModalBar: setStrikePosition parameter is greater than 1.0!" << std::endl; strikePosition = 1.0; } // Hack only first three modes. MY_FLOAT temp2 = position * ONE_PI; MY_FLOAT temp = sin(temp2); this->setModeGain(0, 0.12 * temp); temp = sin(0.05 + (3.9 * temp2)); this->setModeGain(1,(MY_FLOAT) -0.03 * temp); temp = (MY_FLOAT) sin(-0.05 + (11 * temp2)); this->setModeGain(2,(MY_FLOAT) 0.11 * temp); } void ModalBar :: setPreset(int preset) { // Presets: // First line: relative modal frequencies (negative number is // a fixed mode that doesn't scale with frequency // Second line: resonances of the modes // Third line: mode volumes // Fourth line: stickHardness, strikePosition, and direct stick // gain (mixed directly into the output static MY_FLOAT presets[9][4][4] = { {{1.0, 3.99, 10.65, -2443}, // Marimba {0.9996, 0.9994, 0.9994, 0.999}, {0.04, 0.01, 0.01, 0.008}, {0.429688, 0.445312, 0.093750}}, {{1.0, 2.01, 3.9, 14.37}, // Vibraphone {0.99995, 0.99991, 0.99992, 0.9999}, {0.025, 0.015, 0.015, 0.015 }, {0.390625,0.570312,0.078125}}, {{1.0, 4.08, 6.669, -3725.0}, // Agogo {0.999, 0.999, 0.999, 0.999}, {0.06, 0.05, 0.03, 0.02}, {0.609375,0.359375,0.140625}}, {{1.0, 2.777, 7.378, 15.377}, // Wood1 {0.996, 0.994, 0.994, 0.99}, {0.04, 0.01, 0.01, 0.008}, {0.460938,0.375000,0.046875}}, {{1.0, 2.777, 7.378, 15.377}, // Reso {0.99996, 0.99994, 0.99994, 0.9999}, {0.02, 0.005, 0.005, 0.004}, {0.453125,0.250000,0.101562}}, {{1.0, 1.777, 2.378, 3.377}, // Wood2 {0.996, 0.994, 0.994, 0.99}, {0.04, 0.01, 0.01, 0.008}, {0.312500,0.445312,0.109375}}, {{1.0, 1.004, 1.013, 2.377}, // Beats {0.9999, 0.9999, 0.9999, 0.999}, {0.02, 0.005, 0.005, 0.004}, {0.398438,0.296875,0.070312}}, {{1.0, 4.0, -1320.0, -3960.0}, // 2Fix {0.9996, 0.999, 0.9994, 0.999}, {0.04, 0.01, 0.01, 0.008}, {0.453125,0.453125,0.070312}}, {{1.0, 1.217, 1.475, 1.729}, // Clump {0.999, 0.999, 0.999, 0.999}, {0.03, 0.03, 0.03, 0.03 }, {0.390625,0.570312,0.078125}}, }; int temp = (preset % 9); for (int i=0; isetRatioAndRadius(i, presets[temp][0][i], presets[temp][1][i]); this->setModeGain(i, presets[temp][2][i]); } this->setStickHardness(presets[temp][3][0]); this->setStrikePosition(presets[temp][3][1]); directGain = presets[temp][3][2]; if (temp == 1) // vibraphone vibratoGain = 0.2; else vibratoGain = 0.0; } void ModalBar :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): ModalBar: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): ModalBar: Control value greater than 128.0!" << std::endl; } if (number == __SK_StickHardness_) // 2 this->setStickHardness( norm ); else if (number == __SK_StrikePosition_) // 4 this->setStrikePosition( norm ); else if (number == __SK_ProphesyRibbon_) // 16 this->setPreset((int) value); else if (number == __SK_ModWheel_) // 1 directGain = norm; else if (number == 11) { // 11 vibratoGain = norm * 0.3; m_vibratoGain = norm; } else if (number == 7) { // 7 vibrato->setFrequency( norm * 12.0 ); m_vibratoFreq = vibrato->m_freq; } else if (number == __SK_AfterTouch_Cont_) { // 128 envelope->setTarget( norm ); m_volume = norm; } else std::cerr << "[chuck](via STK): ModalBar: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): ModalBar: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Modulate \brief STK periodic/random modulator. This class combines random and periodic modulations to give a nice, natural human modulation function. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Modulate :: Modulate() { // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency( 6.0 ); vibratoGain = 0.04; noise = new SubNoise(330); randomGain = 0.05; filter = new OnePole( 0.999 ); filter->setGain( randomGain ); } Modulate :: ~Modulate() { delete vibrato; delete noise; delete filter; } void Modulate :: reset() { lastOutput = (MY_FLOAT) 0.0; } void Modulate :: setVibratoRate(MY_FLOAT aRate) { vibrato->setFrequency( aRate ); } void Modulate :: setVibratoGain(MY_FLOAT aGain) { vibratoGain = aGain; } void Modulate :: setRandomGain(MY_FLOAT aGain) { randomGain = aGain; filter->setGain( randomGain ); } MY_FLOAT Modulate :: tick() { // Compute periodic and random modulations. lastOutput = vibratoGain * vibrato->tick(); lastOutput += filter->tick( noise->tick() ); return lastOutput; } MY_FLOAT *Modulate :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; isetFrequency((MY_FLOAT) 6.122); filters[0] = new FormSwep(); filters[0]->setTargets( 0.0, 0.7 ); filters[1] = new FormSwep(); filters[1]->setTargets( 0.0, 0.7 ); adsr->setAllTimes((MY_FLOAT) 0.001,(MY_FLOAT) 1.5,(MY_FLOAT) 0.6,(MY_FLOAT) 0.250); filterQ = (MY_FLOAT) 0.85; filterRate = (MY_FLOAT) 0.0001; modDepth = (MY_FLOAT) 0.0; // chuck //reverse: loops[1]->setFrequency(mSpeed); m_vibratoFreq = loops[1]->m_freq; //reverse: modDepth = mDepth * (MY_FLOAT) 0.5; m_vibratoGain = modDepth / 0.5; //reverse: nothing m_volume = 1.0; } Moog :: ~Moog() { delete attacks[0]; delete loops[0]; delete loops[1]; delete filters[0]; delete filters[1]; } void Moog :: setFrequency(MY_FLOAT frequency) { baseFrequency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Moog: setFrequency parameter is less than or equal to zero!" << std::endl; baseFrequency = 220.0; } MY_FLOAT rate = attacks[0]->getSize() * 0.01 * baseFrequency / sampleRate(); attacks[0]->setRate( rate ); loops[0]->setFrequency(baseFrequency); // chuck m_frequency = baseFrequency; } //CHUCK wrapper void Moog :: noteOn(MY_FLOAT amplitude ) { noteOn ( baseFrequency, amplitude ); } void Moog :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { MY_FLOAT temp; this->setFrequency( frequency ); this->keyOn(); attackGain = amplitude * (MY_FLOAT) 0.5; loopGain = amplitude; temp = filterQ + (MY_FLOAT) 0.05; filters[0]->setStates( 2000.0, temp ); filters[1]->setStates( 2000.0, temp ); temp = filterQ + (MY_FLOAT) 0.099; filters[0]->setTargets( frequency, temp ); filters[1]->setTargets( frequency, temp ); filters[0]->setSweepRate( filterRate * 22050.0 / Stk::sampleRate() ); filters[1]->setSweepRate( filterRate * 22050.0 / Stk::sampleRate() ); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Moog: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Moog :: setModulationSpeed(MY_FLOAT mSpeed) { loops[1]->setFrequency(mSpeed); m_vibratoFreq = loops[1]->m_freq; } void Moog :: setModulationDepth(MY_FLOAT mDepth) { modDepth = mDepth * (MY_FLOAT) 0.5; m_vibratoGain = mDepth; } MY_FLOAT Moog :: tick() { MY_FLOAT temp; if ( modDepth != 0.0 ) { temp = loops[1]->tick() * modDepth; loops[0]->setFrequency( baseFrequency * (1.0 + temp) ); } temp = Sampler::tick(); temp = filters[0]->tick( temp ); lastOutput = filters[1]->tick( temp ); return lastOutput * 3.0; } void Moog :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Moog: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Moog: Control value greater than 128.0!" << std::endl; } if (number == __SK_FilterQ_) // 2 filterQ = 0.80 + ( 0.1 * norm ); else if (number == __SK_FilterSweepRate_) // 4 filterRate = norm * 0.0002; else if (number == __SK_ModFrequency_) { // 11 this->setModulationSpeed( norm * 12.0 ); } else if (number == __SK_ModWheel_) { // 1 this->setModulationDepth( norm ); } else if (number == __SK_AfterTouch_Cont_) { // 128 adsr->setTarget( norm ); m_volume = norm; } else std::cerr << "[chuck](via STK): Moog: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Moog: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class NRev \brief CCRMA's NRev reverberator class. This class is derived from the CLM NRev function, which is based on the use of networks of simple allpass and comb delay filters. This particular arrangement consists of 6 comb filters in parallel, followed by 3 allpass filters, a lowpass filter, and another allpass in series, followed by two allpass filters in parallel with corresponding right and left outputs. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include NRev :: NRev(MY_FLOAT T60) { int lengths[15] = {1433, 1601, 1867, 2053, 2251, 2399, 347, 113, 37, 59, 53, 43, 37, 29, 19}; double scaler = Stk::sampleRate() / 25641.0; int delay, i; for (i=0; i<15; i++) { delay = (int) floor(scaler * lengths[i]); if ( (delay & 1) == 0) delay++; while ( !this->isPrime(delay) ) delay += 2; lengths[i] = delay; } for (i=0; i<6; i++) { combDelays[i] = new Delay( lengths[i], lengths[i]); combCoefficient[i] = pow(10.0, (-3 * lengths[i] / (T60 * Stk::sampleRate()))); } for (i=0; i<8; i++) allpassDelays[i] = new Delay(lengths[i+6], lengths[i+6]); allpassCoefficient = 0.7; effectMix = 0.3; this->clear(); } NRev :: ~NRev() { int i; for (i=0; i<6; i++) delete combDelays[i]; for (i=0; i<8; i++) delete allpassDelays[i]; } void NRev :: clear() { int i; for (i=0; i<6; i++) combDelays[i]->clear(); for (i=0; i<8; i++) allpassDelays[i]->clear(); lastOutput[0] = 0.0; lastOutput[1] = 0.0; lowpassState = 0.0; } MY_FLOAT NRev :: tick(MY_FLOAT input) { MY_FLOAT temp, temp0, temp1, temp2, temp3; int i; // gewang: dedenormal CK_STK_DDN(input); temp0 = 0.0; for (i=0; i<6; i++) { temp = input + (combCoefficient[i] * combDelays[i]->lastOut()); // gewang: dedenormal CK_STK_DDN(temp); temp0 += combDelays[i]->tick(temp); } for (i=0; i<3; i++) { temp = allpassDelays[i]->lastOut(); temp1 = allpassCoefficient * temp; temp1 += temp0; // gewang: dedenormal CK_STK_DDN(temp1); allpassDelays[i]->tick(temp1); temp0 = -(allpassCoefficient * temp1) + temp; } // One-pole lowpass filter. lowpassState = 0.7*lowpassState + 0.3*temp0; // gewang: dedenormal CK_STK_DDN(lowpassState); temp = allpassDelays[3]->lastOut(); temp1 = allpassCoefficient * temp; temp1 += lowpassState; // gewang: dedenormal CK_STK_DDN(temp1); allpassDelays[3]->tick(temp1); temp1 = -(allpassCoefficient * temp1) + temp; temp = allpassDelays[4]->lastOut(); temp2 = allpassCoefficient * temp; temp2 += temp1; // gewang: dedenormal CK_STK_DDN(temp2); allpassDelays[4]->tick(temp2); lastOutput[0] = effectMix*(-(allpassCoefficient * temp2) + temp); temp = allpassDelays[5]->lastOut(); temp3 = allpassCoefficient * temp; temp3 += temp1; // gewang: dedenormal CK_STK_DDN(temp3); allpassDelays[5]->tick(temp3); lastOutput[1] = effectMix*(-(allpassCoefficient * temp3) + temp); temp = (1.0 - effectMix) * input; lastOutput[0] += temp; lastOutput[1] += temp; return (lastOutput[0] + lastOutput[1]) * 0.5; } /***************************************************/ /*! \class Noise \brief STK noise generator. Generic random number generation using the C rand() function. The quality of the rand() function varies from one OS to another. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include Noise :: Noise() : Stk() { // Seed the random number generator with system time. this->setSeed( 0 ); lastOutput = (MY_FLOAT) 0.0; } Noise :: Noise( unsigned int seed ) : Stk() { // Seed the random number generator this->setSeed( seed ); lastOutput = (MY_FLOAT) 0.0; } Noise :: ~Noise() { } void Noise :: setSeed( unsigned int seed ) { if ( seed == 0 ) srand( (unsigned int) time(NULL) ); else srand( seed ); } MY_FLOAT Noise :: tick() { lastOutput = (MY_FLOAT) (2.0 * rand() / (RAND_MAX + 1.0) ); lastOutput -= 1.0; return lastOutput; } MY_FLOAT *Noise :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i 0.0) B = (MY_FLOAT) (1.0 - thePole); else B = (MY_FLOAT) (1.0 + thePole); A[1] = -thePole; FilterStk::setCoefficients( 1, &B, 2, A ); } OnePole :: ~OnePole() { } void OnePole :: clear(void) { FilterStk::clear(); } void OnePole :: setB0(MY_FLOAT b0) { b[0] = b0; } void OnePole :: setA1(MY_FLOAT a1) { a[1] = a1; } void OnePole :: setPole(MY_FLOAT thePole) { // Normalize coefficients for peak unity gain. if (thePole > 0.0) b[0] = (MY_FLOAT) (1.0 - thePole); else b[0] = (MY_FLOAT) (1.0 + thePole); a[1] = -thePole; } void OnePole :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT OnePole :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT OnePole :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT OnePole :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[0] * inputs[0] - a[1] * outputs[1]; outputs[1] = outputs[0]; // gewang: dedenormal CK_STK_DDN(outputs[1]); return outputs[0]; } MY_FLOAT *OnePole :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i 0.0) B[0] = 1.0 / ((MY_FLOAT) 1.0 + theZero); else B[0] = 1.0 / ((MY_FLOAT) 1.0 - theZero); B[1] = -theZero * B[0]; FilterStk::setCoefficients( 2, B, 1, &A ); } OneZero :: ~OneZero(void) { } void OneZero :: clear(void) { FilterStk::clear(); } void OneZero :: setB0(MY_FLOAT b0) { b[0] = b0; } void OneZero :: setB1(MY_FLOAT b1) { b[1] = b1; } void OneZero :: setZero(MY_FLOAT theZero) { // Normalize coefficients for unity gain. if (theZero > 0.0) b[0] = 1.0 / ((MY_FLOAT) 1.0 + theZero); else b[0] = 1.0 / ((MY_FLOAT) 1.0 - theZero); b[1] = -theZero * b[0]; } void OneZero :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT OneZero :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT OneZero :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT OneZero :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[1] * inputs[1] + b[0] * inputs[0]; inputs[1] = inputs[0]; return outputs[0]; } MY_FLOAT *OneZero :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i PRCRev :: PRCRev(MY_FLOAT T60) { // Delay lengths for 44100 Hz sample rate. int lengths[4]= {353, 1097, 1777, 2137}; double scaler = Stk::sampleRate() / 44100.0; // Scale the delay lengths if necessary. int delay, i; if ( scaler != 1.0 ) { for (i=0; i<4; i++) { delay = (int) floor(scaler * lengths[i]); if ( (delay & 1) == 0) delay++; while ( !this->isPrime(delay) ) delay += 2; lengths[i] = delay; } } for (i=0; i<2; i++) { allpassDelays[i] = new Delay( lengths[i], lengths[i] ); combDelays[i] = new Delay( lengths[i+2], lengths[i+2] ); combCoefficient[i] = pow(10.0,(-3 * lengths[i+2] / (T60 * Stk::sampleRate()))); } allpassCoefficient = 0.7; effectMix = 0.5; this->clear(); } PRCRev :: ~PRCRev() { delete allpassDelays[0]; delete allpassDelays[1]; delete combDelays[0]; delete combDelays[1]; } void PRCRev :: clear() { allpassDelays[0]->clear(); allpassDelays[1]->clear(); combDelays[0]->clear(); combDelays[1]->clear(); lastOutput[0] = 0.0; lastOutput[1] = 0.0; } MY_FLOAT PRCRev :: tick(MY_FLOAT input) { MY_FLOAT temp, temp0, temp1, temp2, temp3; // gewang: dedenormal CK_STK_DDN(input); temp = allpassDelays[0]->lastOut(); temp0 = allpassCoefficient * temp; temp0 += input; // gewang: dedenormal CK_STK_DDN(temp0); allpassDelays[0]->tick(temp0); temp0 = -(allpassCoefficient * temp0) + temp; temp = allpassDelays[1]->lastOut(); temp1 = allpassCoefficient * temp; temp1 += temp0; // gewang: dedenormal CK_STK_DDN(temp1); allpassDelays[1]->tick(temp1); temp1 = -(allpassCoefficient * temp1) + temp; temp2 = temp1 + (combCoefficient[0] * combDelays[0]->lastOut()); temp3 = temp1 + (combCoefficient[1] * combDelays[1]->lastOut()); // gewang: dedenormal CK_STK_DDN(temp2); CK_STK_DDN(temp3); lastOutput[0] = effectMix * (combDelays[0]->tick(temp2)); lastOutput[1] = effectMix * (combDelays[1]->tick(temp3)); temp = (MY_FLOAT) (1.0 - effectMix) * input; lastOutput[0] += temp; lastOutput[1] += temp; return (lastOutput[0] + lastOutput[1]) * (MY_FLOAT) 0.5; } /***************************************************/ /*! \class PercFlut \brief STK percussive flute FM synthesis instrument. This class implements algorithm 4 of the TX81Z. \code Algorithm 4 is : 4->3--\ 2-- + -->1-->Out \endcode Control Change Numbers: - Total Modulator Index = 2 - Modulator Crossfade = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ PercFlut :: PercFlut() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 1.50 * 1.000); this->setRatio(1, 3.00 * 0.995); this->setRatio(2, 2.99 * 1.005); this->setRatio(3, 6.00 * 0.997); gains[0] = __FM_gains[99]; gains[1] = __FM_gains[71]; gains[2] = __FM_gains[93]; gains[3] = __FM_gains[85]; adsr[0]->setAllTimes( 0.05, 0.05, __FM_susLevels[14], 0.05); adsr[1]->setAllTimes( 0.02, 0.50, __FM_susLevels[13], 0.5); adsr[2]->setAllTimes( 0.02, 0.30, __FM_susLevels[11], 0.05); adsr[3]->setAllTimes( 0.02, 0.05, __FM_susLevels[13], 0.01); twozero->setGain( 0.0 ); modDepth = 0.005; } PercFlut :: ~PercFlut() { } void PercFlut :: setFrequency(MY_FLOAT frequency) { baseFrequency = frequency; // chuck m_frequency = baseFrequency; } void PercFlut :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[99] * 0.5; gains[1] = amplitude * __FM_gains[71] * 0.5; gains[2] = amplitude * __FM_gains[93] * 0.5; gains[3] = amplitude * __FM_gains[85] * 0.5; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "PercFlut: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT PercFlut :: tick() { register MY_FLOAT temp; temp = vibrato->tick() * modDepth * (MY_FLOAT) 0.2; waves[0]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[0]); waves[1]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[1]); waves[2]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[2]); waves[3]->setFrequency(baseFrequency * ((MY_FLOAT) 1.0 + temp) * ratios[3]); waves[3]->addPhaseOffset(twozero->lastOut()); temp = gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); waves[2]->addPhaseOffset(temp); temp = (1.0 - (control2 * 0.5)) * gains[2] * adsr[2]->tick() * waves[2]->tick(); temp += control2 * 0.5 * gains[1] * adsr[1]->tick() * waves[1]->tick(); temp = temp * control1; waves[0]->addPhaseOffset(temp); temp = gains[0] * adsr[0]->tick() * waves[0]->tick(); lastOutput = temp * (MY_FLOAT) 0.5; return lastOutput; } /***************************************************/ /*! \class Phonemes \brief STK phonemes table. This class does nothing other than declare a set of 32 static phoneme formant parameters and provide access to those values. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include const char Phonemes :: phonemeNames[32][4] = {"eee", "ihh", "ehh", "aaa", "ahh", "aww", "ohh", "uhh", "uuu", "ooo", "rrr", "lll", "mmm", "nnn", "nng", "ngg", "fff", "sss", "thh", "shh", "xxx", "hee", "hoo", "hah", "bbb", "ddd", "jjj", "ggg", "vvv", "zzz", "thz", "zhh" }; const MY_FLOAT Phonemes :: phonemeGains[32][2] = {{1.0, 0.0}, // eee {1.0, 0.0}, // ihh {1.0, 0.0}, // ehh {1.0, 0.0}, // aaa {1.0, 0.0}, // ahh {1.0, 0.0}, // aww {1.0, 0.0}, // ohh {1.0, 0.0}, // uhh {1.0, 0.0}, // uuu {1.0, 0.0}, // ooo {1.0, 0.0}, // rrr {1.0, 0.0}, // lll {1.0, 0.0}, // mmm {1.0, 0.0}, // nnn {1.0, 0.0}, // nng {1.0, 0.0}, // ngg {0.0, 0.7}, // fff {0.0, 0.7}, // sss {0.0, 0.7}, // thh {0.0, 0.7}, // shh {0.0, 0.7}, // xxx {0.0, 0.1}, // hee {0.0, 0.1}, // hoo {0.0, 0.1}, // hah {1.0, 0.1}, // bbb {1.0, 0.1}, // ddd {1.0, 0.1}, // jjj {1.0, 0.1}, // ggg {1.0, 1.0}, // vvv {1.0, 1.0}, // zzz {1.0, 1.0}, // thz {1.0, 1.0} // zhh }; const MY_FLOAT Phonemes :: phonemeParameters[32][4][3] = {{ { 273, 0.996, 10}, // eee (beet) {2086, 0.945, -16}, {2754, 0.979, -12}, {3270, 0.440, -17}}, { { 385, 0.987, 10}, // ihh (bit) {2056, 0.930, -20}, {2587, 0.890, -20}, {3150, 0.400, -20}}, { { 515, 0.977, 10}, // ehh (bet) {1805, 0.810, -10}, {2526, 0.875, -10}, {3103, 0.400, -13}}, { { 773, 0.950, 10}, // aaa (bat) {1676, 0.830, -6}, {2380, 0.880, -20}, {3027, 0.600, -20}}, { { 770, 0.950, 0}, // ahh (father) {1153, 0.970, -9}, {2450, 0.780, -29}, {3140, 0.800, -39}}, { { 637, 0.910, 0}, // aww (bought) { 895, 0.900, -3}, {2556, 0.950, -17}, {3070, 0.910, -20}}, { { 637, 0.910, 0}, // ohh (bone) NOTE:: same as aww (bought) { 895, 0.900, -3}, {2556, 0.950, -17}, {3070, 0.910, -20}}, { { 561, 0.965, 0}, // uhh (but) {1084, 0.930, -10}, {2541, 0.930, -15}, {3345, 0.900, -20}}, { { 515, 0.976, 0}, // uuu (foot) {1031, 0.950, -3}, {2572, 0.960, -11}, {3345, 0.960, -20}}, { { 349, 0.986, -10}, // ooo (boot) { 918, 0.940, -20}, {2350, 0.960, -27}, {2731, 0.950, -33}}, { { 394, 0.959, -10}, // rrr (bird) {1297, 0.780, -16}, {1441, 0.980, -16}, {2754, 0.950, -40}}, { { 462, 0.990, +5}, // lll (lull) {1200, 0.640, -10}, {2500, 0.200, -20}, {3000, 0.100, -30}}, { { 265, 0.987, -10}, // mmm (mom) {1176, 0.940, -22}, {2352, 0.970, -20}, {3277, 0.940, -31}}, { { 204, 0.980, -10}, // nnn (nun) {1570, 0.940, -15}, {2481, 0.980, -12}, {3133, 0.800, -30}}, { { 204, 0.980, -10}, // nng (sang) NOTE:: same as nnn {1570, 0.940, -15}, {2481, 0.980, -12}, {3133, 0.800, -30}}, { { 204, 0.980, -10}, // ngg (bong) NOTE:: same as nnn {1570, 0.940, -15}, {2481, 0.980, -12}, {3133, 0.800, -30}}, { {1000, 0.300, 0}, // fff {2800, 0.860, -10}, {7425, 0.740, 0}, {8140, 0.860, 0}}, { {0, 0.000, 0}, // sss {2000, 0.700, -15}, {5257, 0.750, -3}, {7171, 0.840, 0}}, { { 100, 0.900, 0}, // thh {4000, 0.500, -20}, {5500, 0.500, -15}, {8000, 0.400, -20}}, { {2693, 0.940, 0}, // shh {4000, 0.720, -10}, {6123, 0.870, -10}, {7755, 0.750, -18}}, { {1000, 0.300, -10}, // xxx NOTE:: Not Really Done Yet {2800, 0.860, -10}, {7425, 0.740, 0}, {8140, 0.860, 0}}, { { 273, 0.996, -40}, // hee (beet) (noisy eee) {2086, 0.945, -16}, {2754, 0.979, -12}, {3270, 0.440, -17}}, { { 349, 0.986, -40}, // hoo (boot) (noisy ooo) { 918, 0.940, -10}, {2350, 0.960, -17}, {2731, 0.950, -23}}, { { 770, 0.950, -40}, // hah (father) (noisy ahh) {1153, 0.970, -3}, {2450, 0.780, -20}, {3140, 0.800, -32}}, { {2000, 0.700, -20}, // bbb NOTE:: Not Really Done Yet {5257, 0.750, -15}, {7171, 0.840, -3}, {9000, 0.900, 0}}, { { 100, 0.900, 0}, // ddd NOTE:: Not Really Done Yet {4000, 0.500, -20}, {5500, 0.500, -15}, {8000, 0.400, -20}}, { {2693, 0.940, 0}, // jjj NOTE:: Not Really Done Yet {4000, 0.720, -10}, {6123, 0.870, -10}, {7755, 0.750, -18}}, { {2693, 0.940, 0}, // ggg NOTE:: Not Really Done Yet {4000, 0.720, -10}, {6123, 0.870, -10}, {7755, 0.750, -18}}, { {2000, 0.700, -20}, // vvv NOTE:: Not Really Done Yet {5257, 0.750, -15}, {7171, 0.840, -3}, {9000, 0.900, 0}}, { { 100, 0.900, 0}, // zzz NOTE:: Not Really Done Yet {4000, 0.500, -20}, {5500, 0.500, -15}, {8000, 0.400, -20}}, { {2693, 0.940, 0}, // thz NOTE:: Not Really Done Yet {4000, 0.720, -10}, {6123, 0.870, -10}, {7755, 0.750, -18}}, { {2693, 0.940, 0}, // zhh NOTE:: Not Really Done Yet {4000, 0.720, -10}, {6123, 0.870, -10}, {7755, 0.750, -18}} }; Phonemes :: Phonemes(void) { } Phonemes :: ~Phonemes(void) { } const char *Phonemes :: name( unsigned int index ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: name index is greater than 31!" << std::endl; return 0; } return phonemeNames[index]; } MY_FLOAT Phonemes :: voiceGain( unsigned int index ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: voiceGain index is greater than 31!" << std::endl; return 0.0; } return phonemeGains[index][0]; } MY_FLOAT Phonemes :: noiseGain( unsigned int index ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: noiseGain index is greater than 31!" << std::endl; return 0.0; } return phonemeGains[index][1]; } MY_FLOAT Phonemes :: formantFrequency( unsigned int index, unsigned int partial ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: formantFrequency index is greater than 31!" << std::endl; return 0.0; } if ( partial > 3 ) { std::cerr << "[chuck](via STK): Phonemes: formantFrequency partial is greater than 3!" << std::endl; return 0.0; } return phonemeParameters[index][partial][0]; } MY_FLOAT Phonemes :: formantRadius( unsigned int index, unsigned int partial ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: formantRadius index is greater than 31!" << std::endl; return 0.0; } if ( partial > 3 ) { std::cerr << "[chuck](via STK): Phonemes: formantRadius partial is greater than 3!" << std::endl; return 0.0; } return phonemeParameters[index][partial][1]; } MY_FLOAT Phonemes :: formantGain( unsigned int index, unsigned int partial ) { if ( index > 31 ) { std::cerr << "[chuck](via STK): Phonemes: formantGain index is greater than 31!" << std::endl; return 0.0; } if ( partial > 3 ) { std::cerr << "[chuck](via STK): Phonemes: formantGain partial is greater than 3!" << std::endl; return 0.0; } return phonemeParameters[index][partial][2]; } /***************************************************/ /*! \class PitShift \brief STK simple pitch shifter effect class. This class implements a simple pitch shifter using delay lines. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include PitShift :: PitShift() { delay[0] = 12; delay[1] = 512; delayLine[0] = new DelayL(delay[0], (long) 1024); delayLine[1] = new DelayL(delay[1], (long) 1024); effectMix = (MY_FLOAT) 0.5; rate = 1.0; } PitShift :: ~PitShift() { delete delayLine[0]; delete delayLine[1]; } void PitShift :: clear() { delayLine[0]->clear(); delayLine[1]->clear(); lastOutput = 0.0; } void PitShift :: setEffectMix(MY_FLOAT mix) { effectMix = mix; if ( mix < 0.0 ) { std::cerr << "[chuck](via STK): PitShift: setEffectMix parameter is less than zero!" << std::endl; effectMix = 0.0; } else if ( mix > 1.0 ) { std::cerr << "[chuck](via STK): PitShift: setEffectMix parameter is greater than 1.0!" << std::endl; effectMix = 1.0; } } void PitShift :: setShift(MY_FLOAT shift) { if (shift < 1.0) { rate = 1.0 - shift; } else if (shift > 1.0) { rate = 1.0 - shift; } else { rate = 0.0; delay[0] = 512; } } MY_FLOAT PitShift :: lastOut() const { return lastOutput; } MY_FLOAT PitShift :: tick(MY_FLOAT input) { delay[0] = delay[0] + rate; while (delay[0] > 1012) delay[0] -= 1000; while (delay[0] < 12) delay[0] += 1000; delay[1] = delay[0] + 500; while (delay[1] > 1012) delay[1] -= 1000; while (delay[1] < 12) delay[1] += 1000; delayLine[0]->setDelay((long)delay[0]); delayLine[1]->setDelay((long)delay[1]); env[1] = fabs(delay[0] - 512) * 0.002; env[0] = 1.0 - env[1]; lastOutput = env[0] * delayLine[0]->tick(input); lastOutput += env[1] * delayLine[1]->tick(input); lastOutput *= effectMix; lastOutput += (1.0 - effectMix) * input; return lastOutput; } MY_FLOAT *PitShift :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; iclear(); delayLine2->clear(); combDelay->clear(); filter->clear(); filter2->clear(); } void PluckTwo :: setFrequency(MY_FLOAT frequency) { lastFrequency = frequency; if ( lastFrequency <= 0.0 ) { std::cerr << "[chuck](via STK): PluckTwo: setFrequency parameter less than or equal to zero!" << std::endl; lastFrequency = 220.0; } // Delay = length - approximate filter delay. lastLength = ( Stk::sampleRate() / lastFrequency); MY_FLOAT delay = (lastLength / detuning) - (MY_FLOAT) 0.5; if ( delay <= 0.0 ) delay = 0.3; else if ( delay > length ) delay = length; delayLine->setDelay( delay ); delay = (lastLength * detuning) - (MY_FLOAT) 0.5; if ( delay <= 0.0 ) delay = 0.3; else if ( delay > length ) delay = length; delayLine2->setDelay( delay ); loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005); if ( loopGain > 1.0 ) loopGain = (MY_FLOAT) 0.99999; // chuck m_frequency = lastFrequency; } void PluckTwo :: setDetune(MY_FLOAT detune) { detuning = detune; if ( detuning <= 0.0 ) { std::cerr << "[chuck](via STK): PluckTwo: setDetune parameter less than or equal to zero!" << std::endl; detuning = 0.1; } delayLine->setDelay(( lastLength / detuning) - (MY_FLOAT) 0.5); delayLine2->setDelay( (lastLength * detuning) - (MY_FLOAT) 0.5); } void PluckTwo :: setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune) { detuning = detune; this->setFrequency(frequency); } void PluckTwo :: setPluckPosition(MY_FLOAT position) { pluckPosition = position; if ( position < 0.0 ) { std::cerr << "[chuck](via STK): PluckTwo: setPluckPosition parameter is less than zero!" << std::endl; pluckPosition = 0.0; } else if ( position > 1.0 ) { std::cerr << "[chuck](via STK): PluckTwo: setPluckPosition parameter is greater than 1.0!" << std::endl; pluckPosition = 1.0; } } void PluckTwo :: setBaseLoopGain(MY_FLOAT aGain) { baseLoopGain = aGain; loopGain = baseLoopGain + (lastFrequency * (MY_FLOAT) 0.000005); if ( loopGain > 0.99999 ) loopGain = (MY_FLOAT) 0.99999; } void PluckTwo :: noteOff(MY_FLOAT amplitude) { loopGain = ((MY_FLOAT) 1.0 - amplitude) * (MY_FLOAT) 0.5; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): PluckTwo: NoteOff amplitude = " << amplitude << std::endl; #endif } /***************************************************/ /*! \class Plucked \brief STK plucked string model class. This class implements a simple plucked string physical model based on the Karplus-Strong algorithm. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. There exist at least two patents, assigned to Stanford, bearing the names of Karplus and/or Strong. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Plucked :: Plucked(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); loopGain = (MY_FLOAT) 0.999; delayLine = new DelayA( (MY_FLOAT)(length / 2.0), length ); loopFilter = new OneZero; pickFilter = new OnePole; noise = new Noise; this->clear(); } Plucked :: ~Plucked() { delete delayLine; delete loopFilter; delete pickFilter; delete noise; } void Plucked :: clear() { delayLine->clear(); loopFilter->clear(); pickFilter->clear(); } void Plucked :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Plucked: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // Delay = length - approximate filter delay. MY_FLOAT delay = (Stk::sampleRate() / freakency) - (MY_FLOAT) 0.5; if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; delayLine->setDelay(delay); loopGain = 0.995 + (freakency * 0.000005); if ( loopGain >= 1.0 ) loopGain = (MY_FLOAT) 0.99999; // chuck m_frequency = freakency; } void Plucked :: pluck(MY_FLOAT amplitude) { MY_FLOAT gain = amplitude; if ( gain > 1.0 ) { std::cerr << "[chuck](via STK): Plucked: pluck amplitude greater than 1.0!" << std::endl; gain = 1.0; } else if ( gain < 0.0 ) { std::cerr << "[chuck](via STK): Plucked: pluck amplitude less than zero!" << std::endl; gain = 0.0; } pickFilter->setPole((MY_FLOAT) 0.999 - (gain * (MY_FLOAT) 0.15)); pickFilter->setGain(gain * (MY_FLOAT) 0.5); for (long i=0; itick( 0.6 * delayLine->lastOut() + pickFilter->tick( noise->tick() ) ); } void Plucked :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); this->pluck(amplitude); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Plucked: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Plucked :: noteOff(MY_FLOAT amplitude) { loopGain = (MY_FLOAT) 1.0 - amplitude; if ( loopGain < 0.0 ) { std::cerr << "[chuck](via STK): Plucked: noteOff amplitude greater than 1.0!" << std::endl; loopGain = 0.0; } else if ( loopGain > 1.0 ) { std::cerr << "[chuck](via STK): Plucked: noteOff amplitude less than or zero!" << std::endl; loopGain = (MY_FLOAT) 0.99999; } #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Plucked: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Plucked :: tick() { // Here's the whole inner loop of the instrument!! lastOutput = delayLine->tick( loopFilter->tick( delayLine->lastOut() * loopGain ) ); lastOutput *= (MY_FLOAT) 3.0; return lastOutput; } /***************************************************/ /*! \class PoleZero \brief STK one-pole, one-zero filter class. This protected Filter subclass implements a one-pole, one-zero digital filter. A method is provided for creating an allpass filter with a given coefficient. Another method is provided to create a DC blocking filter. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ PoleZero :: PoleZero() : FilterStk() { // Default setting for pass-through. MY_FLOAT B[2] = {1.0, 0.0}; MY_FLOAT A[2] = {1.0, 0.0}; FilterStk::setCoefficients( 2, B, 2, A ); } PoleZero :: ~PoleZero() { } void PoleZero :: clear(void) { FilterStk::clear(); } void PoleZero :: setB0(MY_FLOAT b0) { b[0] = b0; } void PoleZero :: setB1(MY_FLOAT b1) { b[1] = b1; } void PoleZero :: setA1(MY_FLOAT a1) { a[1] = a1; } void PoleZero :: setAllpass(MY_FLOAT coefficient) { b[0] = coefficient; b[1] = 1.0; a[0] = 1.0; // just in case a[1] = coefficient; } void PoleZero :: setBlockZero(MY_FLOAT thePole) { b[0] = 1.0; b[1] = -1.0; a[0] = 1.0; // just in case a[1] = -thePole; } void PoleZero :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT PoleZero :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT PoleZero :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT PoleZero :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[0] * inputs[0] + b[1] * inputs[1] - a[1] * outputs[1]; inputs[1] = inputs[0]; outputs[1] = outputs[0]; // gewang: dedenormal CK_STK_DDN(outputs[1]); return outputs[0]; } MY_FLOAT *PoleZero :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i 1, the reed has slammed shut and the // reflection function value saturates at 1.0. if (lastOutput > 1.0) lastOutput = (MY_FLOAT) 1.0; // This is nearly impossible in a physical system, but // a reflection function value of -1.0 corresponds to // an open end (and no discontinuity in bore profile). if (lastOutput < -1.0) lastOutput = (MY_FLOAT) -1.0; return lastOutput; } MY_FLOAT *ReedTabl :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; isetResonance( poleFrequency, poleRadius, TRUE ); zeroFrequency = 0.0; zeroRadius = 0.0; } Resonate :: ~Resonate() { delete adsr; delete filter; delete noise; } void Resonate :: keyOn() { adsr->keyOn(); } void Resonate :: keyOff() { adsr->keyOff(); } void Resonate :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { adsr->setTarget( amplitude ); this->keyOn(); this->setResonance(frequency, poleRadius); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Resonate: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Resonate :: noteOff(MY_FLOAT amplitude) { this->keyOff(); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Resonate: NoteOff amplitude = " << amplitude << std::endl; #endif } void Resonate :: setResonance(MY_FLOAT frequency, MY_FLOAT radius) { poleFrequency = frequency; if ( frequency < 0.0 ) { std::cerr << "[chuck](via STK): Resonate: setResonance frequency parameter is less than zero!" << std::endl; poleFrequency = 0.0; } poleRadius = radius; if ( radius < 0.0 ) { std::cerr << "[chuck](via STK): Resonate: setResonance radius parameter is less than 0.0!" << std::endl; poleRadius = 0.0; } else if ( radius >= 1.0 ) { std::cerr << "[chuck](via STK): Resonate: setResonance radius parameter is greater than or equal to 1.0, which is unstable!" << std::endl; poleRadius = 0.9999; } filter->setResonance( poleFrequency, poleRadius, TRUE ); } void Resonate :: setNotch(MY_FLOAT frequency, MY_FLOAT radius) { zeroFrequency = frequency; if ( frequency < 0.0 ) { std::cerr << "[chuck](via STK): Resonate: setNotch frequency parameter is less than zero!" << std::endl; zeroFrequency = 0.0; } zeroRadius = radius; if ( radius < 0.0 ) { std::cerr << "[chuck](via STK): Resonate: setNotch radius parameter is less than 0.0!" << std::endl; zeroRadius = 0.0; } filter->setNotch( zeroFrequency, zeroRadius ); } void Resonate :: setEqualGainZeroes() { filter->setEqualGainZeroes(); } MY_FLOAT Resonate :: tick() { lastOutput = filter->tick(noise->tick()); lastOutput *= adsr->tick(); return lastOutput; } void Resonate :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Resonate: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Resonate: Control value greater than 128.0!" << std::endl; } if (number == 2) // 2 setResonance( norm * Stk::sampleRate() * 0.5, poleRadius ); else if (number == 4) // 4 setResonance( poleFrequency, norm*0.9999 ); else if (number == 11) // 11 this->setNotch( norm * Stk::sampleRate() * 0.5, zeroRadius ); else if (number == 1) this->setNotch( zeroFrequency, norm ); else if (number == __SK_AfterTouch_Cont_) // 128 adsr->setTarget( norm ); else std::cerr << "[chuck](via STK): Resonate: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Resonate: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Reverb \brief STK abstract reverberator parent class. This class provides common functionality for STK reverberator subclasses. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Reverb :: Reverb() { } Reverb :: ~Reverb() { } void Reverb :: setEffectMix(MY_FLOAT mix) { effectMix = mix; } MY_FLOAT Reverb :: lastOut() const { return (lastOutput[0] + lastOutput[1]) * 0.5; } MY_FLOAT Reverb :: lastOutLeft() const { return lastOutput[0]; } MY_FLOAT Reverb :: lastOutRight() const { return lastOutput[1]; } MY_FLOAT *Reverb :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Rhodey :: Rhodey() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 1.0); this->setRatio(1, 0.5); this->setRatio(2, 1.0); this->setRatio(3, 15.0); gains[0] = __FM_gains[99]; gains[1] = __FM_gains[90]; gains[2] = __FM_gains[99]; gains[3] = __FM_gains[67]; adsr[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04); adsr[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04); adsr[2]->setAllTimes( 0.001, 1.00, 0.0, 0.04); adsr[3]->setAllTimes( 0.001, 0.25, 0.0, 0.04); twozero->setGain((MY_FLOAT) 1.0); } Rhodey :: ~Rhodey() { } void Rhodey :: setFrequency(MY_FLOAT frequency) { baseFrequency = frequency * (MY_FLOAT) 2.0; for (int i=0; isetFrequency( baseFrequency * ratios[i] ); // chuck m_frequency = baseFrequency * .5; } void Rhodey :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[99]; gains[1] = amplitude * __FM_gains[90]; gains[2] = amplitude * __FM_gains[99]; gains[3] = amplitude * __FM_gains[67]; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "Rhodey: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT Rhodey :: tick() { MY_FLOAT temp, temp2; temp = gains[1] * adsr[1]->tick() * waves[1]->tick(); temp = temp * control1; waves[0]->addPhaseOffset(temp); waves[3]->addPhaseOffset(twozero->lastOut()); temp = gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); waves[2]->addPhaseOffset(temp); temp = ( 1.0 - (control2 * 0.5)) * gains[0] * adsr[0]->tick() * waves[0]->tick(); temp += control2 * 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick(); // Calculate amplitude modulation and apply it to output. temp2 = vibrato->tick() * modDepth; temp = temp * (1.0 + temp2); lastOutput = temp * 0.5; return lastOutput; } /***************************************************/ /*! \class SKINI \brief STK SKINI parsing class This class parses SKINI formatted text messages. It can be used to parse individual messages or it can be passed an entire file. The file specification is Perry's and his alone, but it's all text so it shouldn't be to hard to figure out. SKINI (Synthesis toolKit Instrument Network Interface) is like MIDI, but allows for floating-point control changes, note numbers, etc. The following example causes a sharp middle C to be played with a velocity of 111.132: noteOn 60.01 111.13 See also SKINI.txt. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include // Constructor for use when parsing SKINI strings (coming over socket // for example. Use parseThis() method with string pointer. SKINI :: SKINI() { } // Constructor for reading SKINI files ... use nextMessage() method. SKINI :: SKINI(char *fileName) { char msg[256]; myFile = fopen(fileName,"r"); if ((long) myFile < 0) { sprintf(msg, "[chuck](via SKINI): Could not open or find file (%s).", fileName); handleError(msg, StkError::FILE_NOT_FOUND); } this->nextMessage(); } SKINI :: ~SKINI() { } /***************** SOME HANDY ROUTINES *******************/ #define __SK_MAX_FIELDS_ 5 #define __SK_MAX_SIZE_ 32 short ignore(char aChar) { short ignoreIt = 0; if (aChar == 0) ignoreIt = 1; // Null String Termination if (aChar == '\n') ignoreIt = 1; // Carraige Return??? if (aChar == '/') ignoreIt = 2; // Comment Line return ignoreIt; } short delimit(char aChar) { if (aChar == ' ' || // Space aChar == ',' || // Or Comma aChar == '\t') // Or Tab return 1; else return 0; } short nextChar(char* aString) { int i; for (i=0;i<__SK_MAX_SIZE_;i++) { if ( aString[i] != ' ' && // Space aString[i] != ',' && // Or Comma aString[i] != '\t' ) // Or Tab return i; } return 1024; } int subStrings(char *aString, char someStrings[__SK_MAX_FIELDS_][__SK_MAX_SIZE_], int somePointrs[__SK_MAX_FIELDS_], char *remainderString) { int notDone,howMany,point,temp; notDone = 1; howMany = 0; point = 0; temp = nextChar(aString); if (temp >= __SK_MAX_SIZE_) { notDone = 0; // printf("Confusion here: Ignoring this line\n"); // printf("%s\n",aString); return howMany; } point = temp; somePointrs[howMany] = point; temp = 0; while (notDone) { if (aString[point] == '\n') { notDone = 0; } else { someStrings[howMany][temp++] = aString[point++]; if (temp >= __SK_MAX_SIZE_) { howMany = 0; return howMany; } if (delimit(aString[point]) || aString[point] == '\n') { someStrings[howMany][temp] = 0; howMany += 1; if (howMany < __SK_MAX_FIELDS_) { temp = nextChar(&aString[point]); point += temp; somePointrs[howMany-1] = point; temp = 0; } else { temp = 0; somePointrs[howMany-1] = point; while(aString[point] != '\n') remainderString[temp++] = aString[point++]; remainderString[temp] = aString[point]; } } } } // printf("Got: %i Strings:\n",howMany); // for (temp=0;temp 0) which = 0; aField = 0; strcpy(msgTypeString,someStrings[aField]); while ((which < __SK_MaxMsgTypes_) && (strcmp(msgTypeString, skini_msgs[which].messageString))) { which += 1; } if (which >= __SK_MaxMsgTypes_) { messageType = 0; printf("Couldn't parse this message field: =%s\n %s\n", msgTypeString,aString); return messageType; } else { messageType = skini_msgs[which].type; // printf("Message Token = %s type = %i\n", msgTypeString,messageType); } aField += 1; if (someStrings[aField][0] == '=') { deltaTime = (MY_FLOAT) atof(&someStrings[aField][1]); deltaTime = -deltaTime; } else { deltaTime = (MY_FLOAT) atof(someStrings[aField]); } // printf("DeltaTime = %f\n",deltaTime); aField += 1; channel = atoi(someStrings[aField]); // printf("Channel = %i\n",channel); aField += 1; if (skini_msgs[which].data2 != NOPE) { if (skini_msgs[which].data2 == SK_INT) { byteTwoInt = atoi(someStrings[aField]); byteTwo = (MY_FLOAT) byteTwoInt; } else if (skini_msgs[which].data2 == SK_DBL) { byteTwo = (MY_FLOAT) atof(someStrings[aField]); byteTwoInt = (long) byteTwo; } else if (skini_msgs[which].data2 == SK_STR) { temp = somePointrs[aField-1]; /* Hack Danger Here, Why -1??? */ temp2 = 0; while (aString[temp] != '\n') { remainderString[temp2++] = aString[temp++]; } remainderString[temp2] = 0; } else { byteTwoInt = skini_msgs[which].data2; byteTwo = (MY_FLOAT) byteTwoInt; aField -= 1; } aField += 1; if (skini_msgs[which].data3 != NOPE) { if (skini_msgs[which].data3 == SK_INT) { byteThreeInt = atoi(someStrings[aField]); byteThree = (MY_FLOAT) byteThreeInt; } else if (skini_msgs[which].data3 == SK_DBL) { byteThree = (MY_FLOAT) atof(someStrings[aField]); byteThreeInt = (long) byteThree; } else if (skini_msgs[which].data3 == SK_STR) { temp = somePointrs[aField-1]; /* Hack Danger Here, Why -1??? */ temp2 = 0; while (aString[temp] != '\n') { remainderString[temp2++] = aString[temp++]; } remainderString[temp2] = 0; } else { byteThreeInt = skini_msgs[which].data3; byteThree = (MY_FLOAT) byteThreeInt; } } else { byteThreeInt = byteTwoInt; byteThree = byteTwo; } } } return messageType; } long SKINI :: nextMessage() { int notDone; char inputString[1024]; notDone = 1; while (notDone) { notDone = 0; if (!fgets(inputString,1024,myFile)) { printf("// End of Score. Thanks for using SKINI!!\n"); messageType = -1; return messageType; } else if (parseThis(inputString) == 0) { notDone = 1; } } return messageType; } long SKINI :: getType() const { return messageType; } long SKINI :: getChannel() const { return channel; } MY_FLOAT SKINI :: getDelta() const { return deltaTime; } MY_FLOAT SKINI :: getByteTwo() const { return byteTwo; } long SKINI :: getByteTwoInt() const { return byteTwoInt; } MY_FLOAT SKINI :: getByteThree() const { return byteThree; } long SKINI :: getByteThreeInt() const { return byteThreeInt; } const char* SKINI :: getRemainderString() { return remainderString; } const char* SKINI :: getMessageTypeString() { return msgTypeString; } const char* SKINI :: whatsThisType(long type) { int i = 0; whatString[0] = 0; for ( i=0; i<__SK_MaxMsgTypes_; i++ ) { if ( type == skini_msgs[i].type ) { strcat(whatString, skini_msgs[i].messageString); strcat(whatString, ","); } } return whatString; } const char* SKINI :: whatsThisController(long contNum) { int i = 0; whatString[0] = 0; for ( i=0; i<__SK_MaxMsgTypes_; i++) { if ( skini_msgs[i].type == __SK_ControlChange_ && contNum == skini_msgs[i].data2) { strcat(whatString, skini_msgs[i].messageString); strcat(whatString, ","); } } return whatString; } /***************************************************/ /*! \class Sampler \brief STK sampling synthesis abstract base class. This instrument contains up to 5 attack waves, 5 looped waves, and an ADSR envelope. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Sampler :: Sampler() { // We don't make the waves here yet, because // we don't know what they will be. adsr = new ADSR; baseFrequency = 440.0; filter = new OnePole; attackGain = 0.25; loopGain = 0.25; whichOne = 0; // chuck m_frequency = baseFrequency; } Sampler :: ~Sampler() { delete adsr; delete filter; } void Sampler :: keyOn() { adsr->keyOn(); attacks[0]->reset(); } void Sampler :: keyOff() { adsr->keyOff(); } void Sampler :: noteOff(MY_FLOAT amplitude) { this->keyOff(); #if defined(_STK_DEBUG_) cerr << "Sampler: NoteOff amplitude = " << amplitude << endl; #endif } MY_FLOAT Sampler :: tick() { lastOutput = attackGain * attacks[whichOne]->tick(); lastOutput += loopGain * loops[whichOne]->tick(); lastOutput = filter->tick(lastOutput); lastOutput *= adsr->tick(); return lastOutput; } /***************************************************/ /*! \class Saxofony \brief STK faux conical bore reed instrument class. This class implements a "hybrid" digital waveguide instrument that can generate a variety of wind-like sounds. It has also been referred to as the "blowed string" model. The waveguide section is essentially that of a string, with one rigid and one lossy termination. The non-linear function is a reed table. The string can be "blown" at any point between the terminations, though just as with strings, it is impossible to excite the system at either end. If the excitation is placed at the string mid-point, the sound is that of a clarinet. At points closer to the "bridge", the sound is closer to that of a saxophone. See Scavone (2002) for more details. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Reed Stiffness = 2 - Reed Aperture = 26 - Noise Gain = 4 - Blow Position = 11 - Vibrato Frequency = 29 - Vibrato Gain = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Saxofony :: Saxofony(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); // Initialize blowing position to 0.2 of length / 2. position = 0.2; delays[0] = (DelayL *) new DelayL( (1.0-position) * (length >> 1), length ); delays[1] = (DelayL *) new DelayL( position * (length >> 1), length ); reedTable = new ReedTabl; reedTable->setOffset((MY_FLOAT) 0.7); reedTable->setSlope((MY_FLOAT) 0.3); filter = new OneZero; envelope = new Envelope; noise = new Noise; // Concatenate the STK rawwave path to the rawwave file vibrato = new WaveLoop( "special:sinewave", TRUE ); vibrato->setFrequency((MY_FLOAT) 5.735); outputGain = (MY_FLOAT) 0.3; noiseGain = (MY_FLOAT) 0.2; vibratoGain = (MY_FLOAT) 0.1; // TODO: what is default? m_frequency = length >> 1; // assuming 1.0 velocity m_rate = .005; // reverse: reedTable->setSlope( 0.1 + (0.4 * norm) ) m_stiffness = (reedTable->slope - .1) / .4; // reverse: reedTable->setOffset(0.4 + ( norm * 0.6)); m_aperture = (reedTable->offSet - .4) / .6; // reverse: noiseGain = ( norm * 0.4 ); m_noiseGain = noiseGain / .4; // reverse: vibratoGain = ( norm * 0.5 ); m_vibratoGain = vibratoGain / .5; // pressure from envelope m_pressure = envelope->value; } Saxofony :: ~Saxofony() { delete delays[0]; delete delays[1]; delete reedTable; delete filter; delete envelope; delete noise; delete vibrato; } void Saxofony :: clear() { delays[0]->clear(); delays[1]->clear(); filter->tick((MY_FLOAT) 0.0); } void Saxofony :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Saxofony: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } // chuck m_frequency = freakency; MY_FLOAT delay = (Stk::sampleRate() / freakency) - (MY_FLOAT) 3.0; if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; delays[0]->setDelay((1.0-position) * delay); delays[1]->setDelay(position * delay); } void Saxofony :: setBlowPosition(MY_FLOAT aPosition) { if (position == aPosition) return; if (aPosition < 0.0) position = 0.0; else if (aPosition > 1.0) position = 1.0; else position = aPosition; MY_FLOAT total_delay = delays[0]->getDelay(); total_delay += delays[1]->getDelay(); delays[0]->setDelay((1.0-position) * total_delay); delays[1]->setDelay(position * total_delay); } void Saxofony :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget(amplitude); } void Saxofony :: stopBlowing(MY_FLOAT rate) { envelope->setRate(rate); envelope->setTarget((MY_FLOAT) 0.0); } void Saxofony :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); startBlowing((MY_FLOAT) 0.55 + (amplitude * 0.30), amplitude * 0.005); outputGain = amplitude + 0.001; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Saxofony: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Saxofony :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.01); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Saxofony: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Saxofony :: tick() { MY_FLOAT pressureDiff; MY_FLOAT breathPressure; MY_FLOAT temp; // Calculate the breath pressure (envelope + noise + vibrato) breathPressure = envelope->tick(); breathPressure += breathPressure * noiseGain * noise->tick(); breathPressure += breathPressure * vibratoGain * vibrato->tick(); temp = -0.95 * filter->tick( delays[0]->lastOut() ); lastOutput = temp - delays[1]->lastOut(); pressureDiff = breathPressure - lastOutput; delays[1]->tick(temp); delays[0]->tick(breathPressure - (pressureDiff * reedTable->tick(pressureDiff)) - temp); lastOutput *= outputGain; return lastOutput; } void Saxofony :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Saxofony: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Saxofony: Control value greater than 128.0!" << std::endl; } if (number == __SK_ReedStiffness_) { // 2 reedTable->setSlope( 0.1 + (0.4 * norm) ); m_stiffness = norm; } else if (number == __SK_NoiseLevel_) { // 4 noiseGain = ( norm * 0.4 ); m_noiseGain = norm; } else if (number == 29) // 29 vibrato->setFrequency( norm * 12.0 ); else if (number == __SK_ModWheel_) { // 1 vibratoGain = ( norm * 0.5 ); m_vibratoGain = norm; } else if (number == __SK_AfterTouch_Cont_) { // 128 envelope->setValue( norm ); m_pressure = norm; } else if (number == 11) // 11 this->setBlowPosition( norm ); else if (number == 26) { // reed table offset reedTable->setOffset(0.4 + ( norm * 0.6)); m_aperture = norm; } else std::cerr << "[chuck](via STK): Saxofony: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Saxofony: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Shakers \brief PhISEM and PhOLIES class. PhISEM (Physically Informed Stochastic Event Modeling) is an algorithmic approach for simulating collisions of multiple independent sound producing objects. This class is a meta-model that can simulate a Maraca, Sekere, Cabasa, Bamboo Wind Chimes, Water Drops, Tambourine, Sleighbells, and a Guiro. PhOLIES (Physically-Oriented Library of Imitated Environmental Sounds) is a similar approach for the synthesis of environmental sounds. This class implements simulations of breaking sticks, crunchy snow (or not), a wrench, sandpaper, and more. Control Change Numbers: - Shake Energy = 2 - System Decay = 4 - Number Of Objects = 11 - Resonance Frequency = 1 - Shake Energy = 128 - Instrument Selection = 1071 - Maraca = 0 - Cabasa = 1 - Sekere = 2 - Guiro = 3 - Water Drops = 4 - Bamboo Chimes = 5 - Tambourine = 6 - Sleigh Bells = 7 - Sticks = 8 - Crunch = 9 - Wrench = 10 - Sand Paper = 11 - Coke Can = 12 - Next Mug = 13 - Penny + Mug = 14 - Nickle + Mug = 15 - Dime + Mug = 16 - Quarter + Mug = 17 - Franc + Mug = 18 - Peso + Mug = 19 - Big Rocks = 20 - Little Rocks = 21 - Tuned Bamboo Chimes = 22 by Perry R. Cook, 1996 - 1999. */ /***************************************************/ #include #include #include int my_random(int max) // Return Random Int Between 0 and max { int temp = (int) ((float)max * rand() / (RAND_MAX + 1.0) ); return temp; } MY_FLOAT float_random(MY_FLOAT max) // Return random float between 0.0 and max { MY_FLOAT temp = (MY_FLOAT) (max * rand() / (RAND_MAX + 1.0) ); return temp; } MY_FLOAT noise_tick() // Return random MY_FLOAT float between -1.0 and 1.0 { MY_FLOAT temp = (MY_FLOAT) (2.0 * rand() / (RAND_MAX + 1.0) ); temp -= 1.0; return temp; } // Maraca #define MARA_SOUND_DECAY 0.95 #define MARA_SYSTEM_DECAY 0.999 #define MARA_GAIN 20.0 #define MARA_NUM_BEANS 25 #define MARA_CENTER_FREQ 3200.0 #define MARA_RESON 0.96 // Sekere #define SEKE_SOUND_DECAY 0.96 #define SEKE_SYSTEM_DECAY 0.999 #define SEKE_GAIN 20.0 #define SEKE_NUM_BEANS 64 #define SEKE_CENTER_FREQ 5500.0 #define SEKE_RESON 0.6 // Sandpaper #define SANDPAPR_SOUND_DECAY 0.999 #define SANDPAPR_SYSTEM_DECAY 0.999 #define SANDPAPR_GAIN 0.5 #define SANDPAPR_NUM_GRAINS 128 #define SANDPAPR_CENTER_FREQ 4500.0 #define SANDPAPR_RESON 0.6 // Cabasa #define CABA_SOUND_DECAY 0.96 #define CABA_SYSTEM_DECAY 0.997 #define CABA_GAIN 40.0 #define CABA_NUM_BEADS 512 #define CABA_CENTER_FREQ 3000.0 #define CABA_RESON 0.7 // Bamboo Wind Chimes #define BAMB_SOUND_DECAY 0.95 #define BAMB_SYSTEM_DECAY 0.9999 #define BAMB_GAIN 2.0 #define BAMB_NUM_TUBES 1.25 #define BAMB_CENTER_FREQ0 2800.0 #define BAMB_CENTER_FREQ1 0.8 * 2800.0 #define BAMB_CENTER_FREQ2 1.2 * 2800.0 #define BAMB_RESON 0.995 // Tuned Bamboo Wind Chimes (Anklung) #define TBAMB_SOUND_DECAY 0.95 #define TBAMB_SYSTEM_DECAY 0.9999 #define TBAMB_GAIN 1.0 #define TBAMB_NUM_TUBES 1.25 #define TBAMB_CENTER_FREQ0 1046.6 #define TBAMB_CENTER_FREQ1 1174.8 #define TBAMB_CENTER_FREQ2 1397.0 #define TBAMB_CENTER_FREQ3 1568.0 #define TBAMB_CENTER_FREQ4 1760.0 #define TBAMB_CENTER_FREQ5 2093.3 #define TBAMB_CENTER_FREQ6 2350.0 #define TBAMB_RESON 0.996 // Water Drops #define WUTR_SOUND_DECAY 0.95 #define WUTR_SYSTEM_DECAY 0.996 #define WUTR_GAIN 1.0 #define WUTR_NUM_SOURCES 10 #define WUTR_CENTER_FREQ0 450.0 #define WUTR_CENTER_FREQ1 600.0 #define WUTR_CENTER_FREQ2 750.0 #define WUTR_RESON 0.9985 #define WUTR_FREQ_SWEEP 1.0001 // Tambourine #define TAMB_SOUND_DECAY 0.95 #define TAMB_SYSTEM_DECAY 0.9985 #define TAMB_GAIN 5.0 #define TAMB_NUM_TIMBRELS 32 #define TAMB_SHELL_FREQ 2300 #define TAMB_SHELL_GAIN 0.1 #define TAMB_SHELL_RESON 0.96 #define TAMB_CYMB_FREQ1 5600 #define TAMB_CYMB_FREQ2 8100 #define TAMB_CYMB_RESON 0.99 // Sleighbells #define SLEI_SOUND_DECAY 0.97 #define SLEI_SYSTEM_DECAY 0.9994 #define SLEI_GAIN 1.0 #define SLEI_NUM_BELLS 32 #define SLEI_CYMB_FREQ0 2500 #define SLEI_CYMB_FREQ1 5300 #define SLEI_CYMB_FREQ2 6500 #define SLEI_CYMB_FREQ3 8300 #define SLEI_CYMB_FREQ4 9800 #define SLEI_CYMB_RESON 0.99 // Guiro #define GUIR_SOUND_DECAY 0.95 #define GUIR_GAIN 10.0 #define GUIR_NUM_PARTS 128 #define GUIR_GOURD_FREQ 2500.0 #define GUIR_GOURD_RESON 0.97 #define GUIR_GOURD_FREQ2 4000.0 #define GUIR_GOURD_RESON2 0.97 // Wrench #define WRENCH_SOUND_DECAY 0.95 #define WRENCH_GAIN 5 #define WRENCH_NUM_PARTS 128 #define WRENCH_FREQ 3200.0 #define WRENCH_RESON 0.99 #define WRENCH_FREQ2 8000.0 #define WRENCH_RESON2 0.992 // Cokecan #define COKECAN_SOUND_DECAY 0.97 #define COKECAN_SYSTEM_DECAY 0.999 #define COKECAN_GAIN 0.8 #define COKECAN_NUM_PARTS 48 #define COKECAN_HELMFREQ 370 #define COKECAN_HELM_RES 0.99 #define COKECAN_METLFREQ0 1025 #define COKECAN_METLFREQ1 1424 #define COKECAN_METLFREQ2 2149 #define COKECAN_METLFREQ3 3596 #define COKECAN_METL_RES 0.992 // PhOLIES (Physically-Oriented Library of Imitated Environmental // Sounds), Perry Cook, 1997-8 // Stix1 #define STIX1_SOUND_DECAY 0.96 #define STIX1_SYSTEM_DECAY 0.998 #define STIX1_GAIN 30.0 #define STIX1_NUM_BEANS 2 #define STIX1_CENTER_FREQ 5500.0 #define STIX1_RESON 0.6 // Crunch1 #define CRUNCH1_SOUND_DECAY 0.95 #define CRUNCH1_SYSTEM_DECAY 0.99806 #define CRUNCH1_GAIN 20.0 #define CRUNCH1_NUM_BEADS 7 #define CRUNCH1_CENTER_FREQ 800.0 #define CRUNCH1_RESON 0.95 // Nextmug #define NEXTMUG_SOUND_DECAY 0.97 #define NEXTMUG_SYSTEM_DECAY 0.9995 #define NEXTMUG_GAIN 0.8 #define NEXTMUG_NUM_PARTS 3 #define NEXTMUG_FREQ0 2123 #define NEXTMUG_FREQ1 4518 #define NEXTMUG_FREQ2 8856 #define NEXTMUG_FREQ3 10753 #define NEXTMUG_RES 0.997 #define PENNY_FREQ0 11000 #define PENNY_FREQ1 5200 #define PENNY_FREQ2 3835 #define PENNY_RES 0.999 #define NICKEL_FREQ0 5583 #define NICKEL_FREQ1 9255 #define NICKEL_FREQ2 9805 #define NICKEL_RES 0.9992 #define DIME_FREQ0 4450 #define DIME_FREQ1 4974 #define DIME_FREQ2 9945 #define DIME_RES 0.9993 #define QUARTER_FREQ0 1708 #define QUARTER_FREQ1 8863 #define QUARTER_FREQ2 9045 #define QUARTER_RES 0.9995 #define FRANC_FREQ0 5583 #define FRANC_FREQ1 11010 #define FRANC_FREQ2 1917 #define FRANC_RES 0.9995 #define PESO_FREQ0 7250 #define PESO_FREQ1 8150 #define PESO_FREQ2 10060 #define PESO_RES 0.9996 // Big Gravel #define BIGROCKS_SOUND_DECAY 0.98 #define BIGROCKS_SYSTEM_DECAY 0.9965 #define BIGROCKS_GAIN 20.0 #define BIGROCKS_NUM_PARTS 23 #define BIGROCKS_FREQ 6460 #define BIGROCKS_RES 0.932 // Little Gravel #define LITLROCKS_SOUND_DECAY 0.98 #define LITLROCKS_SYSTEM_DECAY 0.99586 #define LITLROCKS_GAIN 20.0 #define LITLROCKS_NUM_PARTS 1600 #define LITLROCKS_FREQ 9000 #define LITLROCKS_RES 0.843 // Finally ... the class code! Shakers :: Shakers() { int i; instType = 0; shakeEnergy = 0.0; nFreqs = 0; sndLevel = 0.0; for ( i=0; isetupNum(instType); // chuck m_energy = totalEnergy; m_decay = systemDecay; m_objects = nObjects; } Shakers :: ~Shakers() { } #define MAX_SHAKE 2000.0 char instrs[NUM_INSTR][10] = { "Maraca", "Cabasa", "Sekere", "Guiro", "Waterdrp", "Bamboo", "Tambourn", "Sleighbl", "Stix1", "Crunch1", "Wrench", "SandPapr", "CokeCan", "NextMug", "PennyMug", "NicklMug", "DimeMug", "QuartMug", "FrancMug", "PesoMug", "BigRocks", "LitlRoks", "TBamboo" }; int Shakers :: setupName(char* instr) { int which = 0; for (int i=0;isetupNum(which); } void Shakers :: setFinalZs(MY_FLOAT z0, MY_FLOAT z1, MY_FLOAT z2) { finalZCoeffs[0] = z0; finalZCoeffs[1] = z1; finalZCoeffs[2] = z2; } void Shakers :: setDecays(MY_FLOAT sndDecay, MY_FLOAT sysDecay) { soundDecay = sndDecay; systemDecay = sysDecay; } int Shakers :: setFreqAndReson(int which, MY_FLOAT freq, MY_FLOAT reson) { if (which < MAX_FREQS) { resons[which] = reson; center_freqs[which] = freq; t_center_freqs[which] = freq; coeffs[which][1] = reson * reson; coeffs[which][0] = -reson * 2.0 * cos(freq * TWO_PI / Stk::sampleRate()); return 1; } else return 0; } int Shakers :: setupNum(int inst) { int i, rv = 0; MY_FLOAT temp; inst %= 23; // chuck hack if (inst == 1) { // Cabasa rv = inst; nObjects = CABA_NUM_BEADS; defObjs[inst] = CABA_NUM_BEADS; setDecays(CABA_SOUND_DECAY, CABA_SYSTEM_DECAY); defDecays[inst] = CABA_SYSTEM_DECAY; decayScale[inst] = 0.97; nFreqs = 1; baseGain = CABA_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0] = temp; freqalloc[0] = 0; setFreqAndReson(0,CABA_CENTER_FREQ,CABA_RESON); setFinalZs(1.0,-1.0,0.0); } else if (inst == 2) { // Sekere rv = inst; nObjects = SEKE_NUM_BEANS; defObjs[inst] = SEKE_NUM_BEANS; this->setDecays(SEKE_SOUND_DECAY,SEKE_SYSTEM_DECAY); defDecays[inst] = SEKE_SYSTEM_DECAY; decayScale[inst] = 0.94; nFreqs = 1; baseGain = SEKE_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0] = temp; freqalloc[0] = 0; this->setFreqAndReson(0,SEKE_CENTER_FREQ,SEKE_RESON); this->setFinalZs(1.0, 0.0, -1.0); } else if (inst == 3) { // Guiro rv = inst; nObjects = GUIR_NUM_PARTS; defObjs[inst] = GUIR_NUM_PARTS; setDecays(GUIR_SOUND_DECAY,1.0); defDecays[inst] = 0.9999; decayScale[inst] = 1.0; nFreqs = 2; baseGain = GUIR_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp; freqalloc[0] = 0; freqalloc[1] = 0; freq_rand[0] = 0.0; freq_rand[1] = 0.0; setFreqAndReson(0,GUIR_GOURD_FREQ,GUIR_GOURD_RESON); setFreqAndReson(1,GUIR_GOURD_FREQ2,GUIR_GOURD_RESON2); ratchet = 0; ratchetPos = 10; } else if (inst == 4) { // Water Drops rv = inst; nObjects = WUTR_NUM_SOURCES; defObjs[inst] = WUTR_NUM_SOURCES; setDecays(WUTR_SOUND_DECAY,WUTR_SYSTEM_DECAY); defDecays[inst] = WUTR_SYSTEM_DECAY; decayScale[inst] = 0.8; nFreqs = 3; baseGain = WUTR_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp; gains[2]=temp; freqalloc[0] = 1; freqalloc[1] = 1; freqalloc[2] = 1; freq_rand[0] = 0.2; freq_rand[1] = 0.2; freq_rand[2] = 0.2; setFreqAndReson(0,WUTR_CENTER_FREQ0,WUTR_RESON); setFreqAndReson(1,WUTR_CENTER_FREQ0,WUTR_RESON); setFreqAndReson(2,WUTR_CENTER_FREQ0,WUTR_RESON); setFinalZs(1.0,0.0,0.0); } else if (inst == 5) { // Bamboo rv = inst; nObjects = BAMB_NUM_TUBES; defObjs[inst] = BAMB_NUM_TUBES; setDecays(BAMB_SOUND_DECAY, BAMB_SYSTEM_DECAY); defDecays[inst] = BAMB_SYSTEM_DECAY; decayScale[inst] = 0.7; nFreqs = 3; baseGain = BAMB_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp; gains[2]=temp; freqalloc[0] = 1; freqalloc[1] = 1; freqalloc[2] = 1; freq_rand[0] = 0.2; freq_rand[1] = 0.2; freq_rand[2] = 0.2; setFreqAndReson(0,BAMB_CENTER_FREQ0,BAMB_RESON); setFreqAndReson(1,BAMB_CENTER_FREQ1,BAMB_RESON); setFreqAndReson(2,BAMB_CENTER_FREQ2,BAMB_RESON); setFinalZs(1.0,0.0,0.0); } else if (inst == 6) { // Tambourine rv = inst; nObjects = TAMB_NUM_TIMBRELS; defObjs[inst] = TAMB_NUM_TIMBRELS; setDecays(TAMB_SOUND_DECAY,TAMB_SYSTEM_DECAY); defDecays[inst] = TAMB_SYSTEM_DECAY; decayScale[inst] = 0.95; nFreqs = 3; baseGain = TAMB_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp*TAMB_SHELL_GAIN; gains[1]=temp*0.8; gains[2]=temp; freqalloc[0] = 0; freqalloc[1] = 1; freqalloc[2] = 1; freq_rand[0] = 0.0; freq_rand[1] = 0.05; freq_rand[2] = 0.05; setFreqAndReson(0,TAMB_SHELL_FREQ,TAMB_SHELL_RESON); setFreqAndReson(1,TAMB_CYMB_FREQ1,TAMB_CYMB_RESON); setFreqAndReson(2,TAMB_CYMB_FREQ2,TAMB_CYMB_RESON); setFinalZs(1.0,0.0,-1.0); } else if (inst == 7) { // Sleighbell rv = inst; nObjects = SLEI_NUM_BELLS; defObjs[inst] = SLEI_NUM_BELLS; setDecays(SLEI_SOUND_DECAY,SLEI_SYSTEM_DECAY); defDecays[inst] = SLEI_SYSTEM_DECAY; decayScale[inst] = 0.9; nFreqs = 5; baseGain = SLEI_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp; gains[2]=temp; gains[3]=temp*0.5; gains[4]=temp*0.3; for (i=0;isetDecays(SANDPAPR_SOUND_DECAY,SANDPAPR_SYSTEM_DECAY); defDecays[inst] = SANDPAPR_SYSTEM_DECAY; decayScale[inst] = 0.97; nFreqs = 1; baseGain = SANDPAPR_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0] = temp; freqalloc[0] = 0; this->setFreqAndReson(0,SANDPAPR_CENTER_FREQ,SANDPAPR_RESON); this->setFinalZs(1.0, 0.0, -1.0); } else if (inst == 12) { // Cokecan rv = inst; nObjects = COKECAN_NUM_PARTS; defObjs[inst] = COKECAN_NUM_PARTS; setDecays(COKECAN_SOUND_DECAY,COKECAN_SYSTEM_DECAY); defDecays[inst] = COKECAN_SYSTEM_DECAY; decayScale[inst] = 0.95; nFreqs = 5; baseGain = COKECAN_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp*1.8; gains[2]=temp*1.8; gains[3]=temp*1.8; gains[4]=temp*1.8; freqalloc[0] = 0; freqalloc[1] = 0; freqalloc[2] = 0; freqalloc[3] = 0; freqalloc[4] = 0; setFreqAndReson(0,COKECAN_HELMFREQ,COKECAN_HELM_RES); setFreqAndReson(1,COKECAN_METLFREQ0,COKECAN_METL_RES); setFreqAndReson(2,COKECAN_METLFREQ1,COKECAN_METL_RES); setFreqAndReson(3,COKECAN_METLFREQ2,COKECAN_METL_RES); setFreqAndReson(4,COKECAN_METLFREQ3,COKECAN_METL_RES); setFinalZs(1.0,0.0,-1.0); } else if (inst>12 && inst<20) { // Nextmug rv = inst; nObjects = NEXTMUG_NUM_PARTS; defObjs[inst] = NEXTMUG_NUM_PARTS; setDecays(NEXTMUG_SOUND_DECAY,NEXTMUG_SYSTEM_DECAY); defDecays[inst] = NEXTMUG_SYSTEM_DECAY; decayScale[inst] = 0.95; nFreqs = 4; baseGain = NEXTMUG_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp*0.8; gains[2]=temp*0.6; gains[3]=temp*0.4; freqalloc[0] = 0; freqalloc[1] = 0; freqalloc[2] = 0; freqalloc[3] = 0; freqalloc[4] = 0; freqalloc[5] = 0; setFreqAndReson(0,NEXTMUG_FREQ0,NEXTMUG_RES); setFreqAndReson(1,NEXTMUG_FREQ1,NEXTMUG_RES); setFreqAndReson(2,NEXTMUG_FREQ2,NEXTMUG_RES); setFreqAndReson(3,NEXTMUG_FREQ3,NEXTMUG_RES); setFinalZs(1.0,0.0,-1.0); if (inst == 14) { // Mug + Penny nFreqs = 7; gains[4] = temp; gains[5] = temp*0.8; gains[6] = temp*0.5; setFreqAndReson(4,PENNY_FREQ0,PENNY_RES); setFreqAndReson(5,PENNY_FREQ1,PENNY_RES); setFreqAndReson(6,PENNY_FREQ2,PENNY_RES); } else if (inst == 15) { // Mug + Nickel nFreqs = 6; gains[4] = temp; gains[5] = temp*0.8; gains[6] = temp*0.5; setFreqAndReson(4,NICKEL_FREQ0,NICKEL_RES); setFreqAndReson(5,NICKEL_FREQ1,NICKEL_RES); setFreqAndReson(6,NICKEL_FREQ2,NICKEL_RES); } else if (inst == 16) { // Mug + Dime nFreqs = 6; gains[4] = temp; gains[5] = temp*0.8; gains[6] = temp*0.5; setFreqAndReson(4,DIME_FREQ0,DIME_RES); setFreqAndReson(5,DIME_FREQ1,DIME_RES); setFreqAndReson(6,DIME_FREQ2,DIME_RES); } else if (inst == 17) { // Mug + Quarter nFreqs = 6; gains[4] = temp*1.3; gains[5] = temp*1.0; gains[6] = temp*0.8; setFreqAndReson(4,QUARTER_FREQ0,QUARTER_RES); setFreqAndReson(5,QUARTER_FREQ1,QUARTER_RES); setFreqAndReson(6,QUARTER_FREQ2,QUARTER_RES); } else if (inst == 18) { // Mug + Franc nFreqs = 6; gains[4] = temp*0.7; gains[5] = temp*0.4; gains[6] = temp*0.3; setFreqAndReson(4,FRANC_FREQ0,FRANC_RES); setFreqAndReson(5,FRANC_FREQ1,FRANC_RES); setFreqAndReson(6,FRANC_FREQ2,FRANC_RES); } else if (inst == 19) { // Mug + Peso nFreqs = 6; gains[4] = temp; gains[5] = temp*1.2; gains[6] = temp*0.7; setFreqAndReson(4,PESO_FREQ0,PESO_RES); setFreqAndReson(5,PESO_FREQ1,PESO_RES); setFreqAndReson(6,PESO_FREQ2,PESO_RES); } } else if (inst == 20) { // Big Rocks nFreqs = 1; rv = inst; nObjects = BIGROCKS_NUM_PARTS; defObjs[inst] = BIGROCKS_NUM_PARTS; setDecays(BIGROCKS_SOUND_DECAY,BIGROCKS_SYSTEM_DECAY); defDecays[inst] = BIGROCKS_SYSTEM_DECAY; decayScale[inst] = 0.95; baseGain = BIGROCKS_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; freqalloc[0] = 1; freq_rand[0] = 0.11; setFreqAndReson(0,BIGROCKS_FREQ,BIGROCKS_RES); setFinalZs(1.0,0.0,-1.0); } else if (inst == 21) { // Little Rocks nFreqs = 1; rv = inst; nObjects = LITLROCKS_NUM_PARTS; defObjs[inst] = LITLROCKS_NUM_PARTS; setDecays(LITLROCKS_SOUND_DECAY,LITLROCKS_SYSTEM_DECAY); defDecays[inst] = LITLROCKS_SYSTEM_DECAY; decayScale[inst] = 0.95; baseGain = LITLROCKS_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; freqalloc[0] = 1; freq_rand[0] = 0.18; setFreqAndReson(0,LITLROCKS_FREQ,LITLROCKS_RES); setFinalZs(1.0,0.0,-1.0); } else if (inst == 22) { // Tuned Bamboo rv = inst; nObjects = TBAMB_NUM_TUBES; defObjs[inst] = TBAMB_NUM_TUBES; setDecays(TBAMB_SOUND_DECAY, TBAMB_SYSTEM_DECAY); defDecays[inst] = TBAMB_SYSTEM_DECAY; decayScale[inst] = 0.7; nFreqs = 7; baseGain = TBAMB_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; gains[1]=temp; gains[2]=temp; gains[3]=temp; gains[4]=temp; gains[5]=temp; gains[6]=temp; freqalloc[0] = 0; freqalloc[1] = 0; freqalloc[2] = 0; freqalloc[3] = 0; freqalloc[4] = 0; freqalloc[5] = 0; freqalloc[6] = 0; freq_rand[0] = 0.0; freq_rand[1] = 0.0; freq_rand[2] = 0.0; freq_rand[3] = 0.0; freq_rand[4] = 0.0; freq_rand[5] = 0.0; freq_rand[6] = 0.0; setFreqAndReson(0,TBAMB_CENTER_FREQ0,TBAMB_RESON); setFreqAndReson(1,TBAMB_CENTER_FREQ1,TBAMB_RESON); setFreqAndReson(2,TBAMB_CENTER_FREQ2,TBAMB_RESON); setFreqAndReson(3,TBAMB_CENTER_FREQ3,TBAMB_RESON); setFreqAndReson(4,TBAMB_CENTER_FREQ4,TBAMB_RESON); setFreqAndReson(5,TBAMB_CENTER_FREQ5,TBAMB_RESON); setFreqAndReson(6,TBAMB_CENTER_FREQ6,TBAMB_RESON); setFinalZs(1.0,0.0,-1.0); } else { // Maraca (inst == 0) or default rv = 0; nObjects = MARA_NUM_BEANS; defObjs[0] = MARA_NUM_BEANS; setDecays(MARA_SOUND_DECAY,MARA_SYSTEM_DECAY); defDecays[0] = MARA_SYSTEM_DECAY; decayScale[inst] = 0.9; nFreqs = 1; baseGain = MARA_GAIN; temp = log(nObjects) * baseGain / (MY_FLOAT) nObjects; gains[0]=temp; freqalloc[0] = 0; setFreqAndReson(0,MARA_CENTER_FREQ,MARA_RESON); setFinalZs(1.0,-1.0,0.0); } // chuck m_noteNum = inst; m_energy = totalEnergy; m_decay = systemDecay; m_objects = nObjects; return rv; } // chuck function! void Shakers :: ck_noteOn(MY_FLOAT amplitude ) { if (instType != m_noteNum) instType = this->setupNum(m_noteNum); shakeEnergy += amplitude * MAX_SHAKE * 0.1; if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE; if (instType==10 || instType==3) ratchetPos += 1; } void Shakers :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { // Yep ... pretty kludgey, but it works! int noteNum = (int) ((12*log(frequency/220.0)/log(2.0)) + 57.01) % 32; m_noteNum = noteNum; if (instType != noteNum) instType = this->setupNum(noteNum); shakeEnergy += amplitude * MAX_SHAKE * 0.1; if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE; if (instType==10 || instType==3) ratchetPos += 1; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Shakers: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Shakers :: noteOff(MY_FLOAT amplitude) { shakeEnergy = 0.0; if (instType==10 || instType==3) ratchetPos = 0; } #define MIN_ENERGY 0.3 MY_FLOAT Shakers :: tick() { MY_FLOAT data; MY_FLOAT temp_rand; int i; if (instType == 4) { if (shakeEnergy > MIN_ENERGY) { lastOutput = wuter_tick(); lastOutput *= 0.0001; } else { lastOutput = 0.0; } } else if (instType == 22) { lastOutput = tbamb_tick(); } else if (instType == 10 || instType == 3) { if (ratchetPos > 0) { ratchet -= (ratchetDelta + (0.002*totalEnergy)); if (ratchet < 0.0) { ratchet = 1.0; ratchetPos -= 1; } totalEnergy = ratchet; lastOutput = ratchet_tick(); lastOutput *= 0.0001; } else lastOutput = 0.0; } else { // MY_FLOAT generic_tick() { if (shakeEnergy > MIN_ENERGY) { shakeEnergy *= systemDecay; // Exponential system decay if (float_random(1024.0) < nObjects) { sndLevel += shakeEnergy; for (i=0;i 10000.0) data = 10000.0; if (data < -10000.0) data = -10000.0; lastOutput = data * 0.0001; } else lastOutput = 0.0; } return lastOutput; } void Shakers :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Shakers: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Shakers: Control value greater than 128.0!" << std::endl; } MY_FLOAT temp; int i; if (number == __SK_Breath_) { // 2 ... energy shakeEnergy += norm * MAX_SHAKE * 0.1; if (shakeEnergy > MAX_SHAKE) shakeEnergy = MAX_SHAKE; if (instType==10 || instType==3) { ratchetPos = (int) fabs(value - lastRatchetPos); ratchetDelta = 0.0002 * ratchetPos; lastRatchetPos = (int) value; } } // else if (number == __SK_ModFrequency_) { // 4 ... decay // CHUCK HACK: (actually this fixes things?) else if (number == __SK_FootControl_) { // 4 ... decay if (instType != 3 && instType != 10) { systemDecay = defDecays[instType] + ((value - 64.0) * decayScale[instType] * (1.0 - defDecays[instType]) / 64.0 ); gains[0] = log(nObjects) * baseGain / (MY_FLOAT) nObjects; for (i=1;i MAX_SHAKE) shakeEnergy = MAX_SHAKE; if (instType==10 || instType==3) { ratchetPos = (int) fabs(value - lastRatchetPos); ratchetDelta = 0.0002 * ratchetPos; lastRatchetPos = (int) value; } } else if (number == __SK_ShakerInst_) { // 1071 instType = (int) (value + 0.5); // Just to be safe this->setupNum(instType); } else std::cerr << "[chuck](via STK): Shakers: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Shakers: controlChange number = " << number << ", value = " << value << std::endl; #endif } // KLUDGE-O-MATIC-O-RAMA MY_FLOAT Shakers :: wuter_tick() { MY_FLOAT data; int j; shakeEnergy *= systemDecay; // Exponential system decay if (my_random(32767) < nObjects) { sndLevel = shakeEnergy; j = my_random(3); if (j == 0) { center_freqs[0] = WUTR_CENTER_FREQ1 * (0.75 + (0.25 * noise_tick())); gains[0] = fabs(noise_tick()); } else if (j == 1) { center_freqs[1] = WUTR_CENTER_FREQ1 * (1.0 + (0.25 * noise_tick())); gains[1] = fabs(noise_tick()); } else { center_freqs[2] = WUTR_CENTER_FREQ1 * (1.25 + (0.25 * noise_tick())); gains[2] = fabs(noise_tick()); } } gains[0] *= resons[0]; if (gains[0] > 0.001) { center_freqs[0] *= WUTR_FREQ_SWEEP; coeffs[0][0] = -resons[0] * 2.0 * cos(center_freqs[0] * TWO_PI / Stk::sampleRate()); } gains[1] *= resons[1]; if (gains[1] > 0.001) { center_freqs[1] *= WUTR_FREQ_SWEEP; coeffs[1][0] = -resons[1] * 2.0 * cos(center_freqs[1] * TWO_PI / Stk::sampleRate()); } gains[2] *= resons[2]; if (gains[2] > 0.001) { center_freqs[2] *= WUTR_FREQ_SWEEP; coeffs[2][0] = -resons[2] * 2.0 * cos(center_freqs[2] * TWO_PI / Stk::sampleRate()); } sndLevel *= soundDecay; // Each (all) event(s) // decay(s) exponentially inputs[0] = sndLevel; inputs[0] *= noise_tick(); // Actual Sound is Random inputs[1] = inputs[0] * gains[1]; inputs[2] = inputs[0] * gains[2]; inputs[0] *= gains[0]; inputs[0] -= outputs[0][0]*coeffs[0][0]; inputs[0] -= outputs[0][1]*coeffs[0][1]; outputs[0][1] = outputs[0][0]; outputs[0][0] = inputs[0]; data = gains[0]*outputs[0][0]; inputs[1] -= outputs[1][0]*coeffs[1][0]; inputs[1] -= outputs[1][1]*coeffs[1][1]; outputs[1][1] = outputs[1][0]; outputs[1][0] = inputs[1]; data += gains[1]*outputs[1][0]; inputs[2] -= outputs[2][0]*coeffs[2][0]; inputs[2] -= outputs[2][1]*coeffs[2][1]; outputs[2][1] = outputs[2][0]; outputs[2][0] = inputs[2]; data += gains[2]*outputs[2][0]; finalZ[2] = finalZ[1]; finalZ[1] = finalZ[0]; finalZ[0] = data * 4; data = finalZ[2] - finalZ[0]; return data; } MY_FLOAT Shakers :: ratchet_tick() { MY_FLOAT data; if (my_random(1024) < nObjects) { sndLevel += 512 * ratchet * totalEnergy; } inputs[0] = sndLevel; inputs[0] *= noise_tick() * ratchet; sndLevel *= soundDecay; inputs[1] = inputs[0]; inputs[0] -= outputs[0][0]*coeffs[0][0]; inputs[0] -= outputs[0][1]*coeffs[0][1]; outputs[0][1] = outputs[0][0]; outputs[0][0] = inputs[0]; inputs[1] -= outputs[1][0]*coeffs[1][0]; inputs[1] -= outputs[1][1]*coeffs[1][1]; outputs[1][1] = outputs[1][0]; outputs[1][0] = inputs[1]; finalZ[2] = finalZ[1]; finalZ[1] = finalZ[0]; finalZ[0] = gains[0]*outputs[0][1] + gains[1]*outputs[1][1]; data = finalZ[0] - finalZ[2]; return data; } MY_FLOAT Shakers :: tbamb_tick() { MY_FLOAT data, temp; static int which = 0; int i; if (shakeEnergy > MIN_ENERGY) { shakeEnergy *= systemDecay; // Exponential system decay if (float_random(1024.0) < nObjects) { sndLevel += shakeEnergy; which = my_random(7); } temp = sndLevel * noise_tick(); // Actual Sound is Random for (i=0;i 10000.0) data = 10000.0; if (data < -10000.0) data = -10000.0; data = data * 0.0001; } else data = 0.0; return data; } /***************************************************/ /*! \class Simple \brief STK wavetable/noise instrument. This class combines a looped wave, a noise source, a biquad resonance filter, a one-pole filter, and an ADSR envelope to create some interesting sounds. Control Change Numbers: - Filter Pole Position = 2 - Noise/Pitched Cross-Fade = 4 - Envelope Rate = 11 - Gain = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Simple :: Simple() { adsr = new ADSR; baseFrequency = (MY_FLOAT) 440.0; // Concatenate the STK rawwave path to the rawwave file loop = new WaveLoop( "special:impuls10", TRUE ); filter = new OnePole(0.5); noise = new Noise; biquad = new BiQuad(); setFrequency(baseFrequency); loopGain = 0.5; } Simple :: ~Simple() { delete adsr; delete loop; delete filter; delete biquad; } void Simple :: keyOn() { adsr->keyOn(); } void Simple :: keyOff() { adsr->keyOff(); } void Simple :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { keyOn(); setFrequency(frequency); filter->setGain(amplitude); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Simple: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Simple :: noteOff(MY_FLOAT amplitude) { keyOff(); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Simple: NoteOff amplitude = " << amplitude << std::endl; #endif } void Simple :: setFrequency(MY_FLOAT frequency) { biquad->setResonance( frequency, 0.98, true ); loop->setFrequency(frequency); // chuck m_frequency = frequency; } MY_FLOAT Simple :: tick() { lastOutput = loopGain * loop->tick(); biquad->tick( noise->tick() ); lastOutput += (1.0 - loopGain) * biquad->lastOut(); lastOutput = filter->tick( lastOutput ); lastOutput *= adsr->tick(); return lastOutput; } void Simple :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Clarinet: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Clarinet: Control value greater than 128.0!" << std::endl; } if (number == __SK_Breath_) // 2 filter->setPole( 0.99 * (1.0 - (norm * 2.0)) ); else if (number == __SK_NoiseLevel_) // 4 loopGain = norm; else if (number == __SK_ModFrequency_) { // 11 norm /= 0.2 * Stk::sampleRate(); adsr->setAttackRate( norm ); adsr->setDecayRate( norm ); adsr->setReleaseRate( norm ); } else if (number == __SK_AfterTouch_Cont_) // 128 adsr->setTarget( norm ); else std::cerr << "[chuck](via STK): Simple: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Simple: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class SingWave \brief STK "singing" looped soundfile class. This class contains all that is needed to make a pitched musical sound, like a simple voice or violin. In general, it will not be used alone because of munchkinification effects from pitch shifting. It will be used as an excitation source for other instruments. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ SingWave :: SingWave(const char *fileName, bool raw) { // An exception could be thrown here. wave = new WaveLoop( fileName, raw ); rate = 1.0; sweepRate = 0.001; modulator = new Modulate(); modulator->setVibratoRate( 6.0 ); modulator->setVibratoGain( 0.04 ); modulator->setRandomGain( 0.005 ); envelope = new Envelope; pitchEnvelope = new Envelope; setFrequency( 75.0 ); pitchEnvelope->setRate( 1.0 ); this->tick(); this->tick(); pitchEnvelope->setRate( sweepRate * rate ); } SingWave :: ~SingWave() { delete wave; delete modulator; delete envelope; delete pitchEnvelope; } void SingWave :: reset() { wave->reset(); lastOutput = 0.0; } void SingWave :: normalize() { wave->normalize(); } void SingWave :: normalize(MY_FLOAT newPeak) { wave->normalize( newPeak ); } void SingWave :: setFrequency(MY_FLOAT frequency) { m_freq = frequency; MY_FLOAT temp = rate; rate = wave->getSize() * frequency / Stk::sampleRate(); temp -= rate; if ( temp < 0) temp = -temp; pitchEnvelope->setTarget( rate ); pitchEnvelope->setRate( sweepRate * temp ); } void SingWave :: setVibratoRate(MY_FLOAT aRate) { modulator->setVibratoRate( aRate ); } void SingWave :: setVibratoGain(MY_FLOAT gain) { modulator->setVibratoGain(gain); } void SingWave :: setRandomGain(MY_FLOAT gain) { modulator->setRandomGain(gain); } void SingWave :: setSweepRate(MY_FLOAT aRate) { sweepRate = aRate; } void SingWave :: setGainRate(MY_FLOAT aRate) { envelope->setRate(aRate); } void SingWave :: setGainTarget(MY_FLOAT target) { envelope->setTarget(target); } void SingWave :: noteOn() { envelope->keyOn(); } void SingWave :: noteOff() { envelope->keyOff(); } MY_FLOAT SingWave :: tick() { // Set the wave rate. MY_FLOAT newRate = pitchEnvelope->tick(); newRate += newRate * modulator->tick(); wave->setRate( newRate ); lastOutput = wave->tick(); lastOutput *= envelope->tick(); return lastOutput; } MY_FLOAT SingWave :: lastOut() { return lastOutput; } /***************************************************/ /*! \class Sitar \brief STK sitar string model class. This class implements a sitar plucked string physical model based on the Karplus-Strong algorithm. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. There exist at least two patents, assigned to Stanford, bearing the names of Karplus and/or Strong. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include Sitar :: Sitar(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); loopGain = (MY_FLOAT) 0.999; delayLine = new DelayA( (MY_FLOAT)(length / 2.0), length ); delay = length / 2.0; targetDelay = delay; loopFilter = new OneZero; loopFilter->setZero(0.01); envelope = new ADSR(); envelope->setAllTimes(0.001, 0.04, 0.0, 0.5); noise = new Noise; this->clear(); } Sitar :: ~Sitar() { delete delayLine; delete loopFilter; delete noise; delete envelope; } void Sitar :: clear() { delayLine->clear(); loopFilter->clear(); } void Sitar :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Sitar: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } targetDelay = (Stk::sampleRate() / freakency); delay = targetDelay * (1.0 + (0.05 * noise->tick())); delayLine->setDelay(delay); loopGain = 0.995 + (freakency * 0.0000005); if (loopGain > 0.9995) loopGain = 0.9995; // chuck m_frequency = freakency; } void Sitar :: pluck(MY_FLOAT amplitude) { envelope->keyOn(); } void Sitar :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); pluck(amplitude); amGain = 0.1 * amplitude; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Sitar: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Sitar :: noteOff(MY_FLOAT amplitude) { loopGain = (MY_FLOAT) 1.0 - amplitude; if ( loopGain < 0.0 ) { std::cerr << "[chuck](via STK): Plucked: noteOff amplitude greater than 1.0!" << std::endl; loopGain = 0.0; } else if ( loopGain > 1.0 ) { std::cerr << "[chuck](via STK): Plucked: noteOff amplitude less than or zero!" << std::endl; loopGain = (MY_FLOAT) 0.99999; } #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Plucked: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT Sitar :: tick() { if ( fabs(targetDelay - delay) > 0.001 ) { if (targetDelay < delay) delay *= 0.99999; else delay *= 1.00001; delayLine->setDelay(delay); } lastOutput = delayLine->tick( loopFilter->tick( delayLine->lastOut() * loopGain ) + (amGain * envelope->tick() * noise->tick())); return lastOutput; } /***************************************************/ /*! \class Sphere \brief STK sphere class. This class implements a spherical ball with radius, mass, position, and velocity parameters. by Perry R. Cook, 1995 - 2002. */ /***************************************************/ #include #include Sphere::Sphere(double initRadius) { myRadius = initRadius; myMass = 1.0; myPosition = new Vector3D(0, 0, 0); myVelocity = new Vector3D(0, 0, 0); }; Sphere::~Sphere() { delete myPosition; delete myVelocity; } void Sphere::setPosition(double anX, double aY, double aZ) { myPosition->setXYZ(anX, aY, aZ); }; void Sphere::setVelocity(double anX, double aY, double aZ) { myVelocity->setXYZ(anX, aY, aZ); }; void Sphere::setRadius(double aRadius) { myRadius = aRadius; }; void Sphere::setMass(double aMass) { myMass = aMass; }; Vector3D* Sphere::getPosition() { return myPosition; }; Vector3D* Sphere::getRelativePosition(Vector3D* aPosition) { workingVector.setXYZ(aPosition->getX() - myPosition->getX(), aPosition->getY() - myPosition->getY(), aPosition->getZ() - myPosition->getZ()); return &workingVector; }; double Sphere::getVelocity(Vector3D* aVelocity) { aVelocity->setXYZ(myVelocity->getX(), myVelocity->getY(), myVelocity->getZ()); return myVelocity->getLength(); }; double Sphere::isInside(Vector3D *aPosition) { // Return directed distance from aPosition to spherical boundary ( < // 0 if inside). double distance; Vector3D *tempVector; tempVector = this->getRelativePosition(aPosition); distance = tempVector->getLength(); return distance - myRadius; }; double Sphere::getRadius() { return myRadius; }; double Sphere::getMass() { return myMass; }; void Sphere::addVelocity(double anX, double aY, double aZ) { myVelocity->setX(myVelocity->getX() + anX); myVelocity->setY(myVelocity->getY() + aY); myVelocity->setZ(myVelocity->getZ() + aZ); } void Sphere::tick(double timeIncrement) { myPosition->setX(myPosition->getX() + (timeIncrement * myVelocity->getX())); myPosition->setY(myPosition->getY() + (timeIncrement * myVelocity->getY())); myPosition->setZ(myPosition->getZ() + (timeIncrement * myVelocity->getZ())); }; /***************************************************/ /*! \class StifKarp \brief STK plucked stiff string instrument. This class implements a simple plucked string algorithm (Karplus Strong) with enhancements (Jaffe-Smith, Smith, and others), including string stiffness and pluck position controls. The stiffness is modeled with allpass filters. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Pickup Position = 4 - String Sustain = 11 - String Stretch = 1 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include StifKarp :: StifKarp(MY_FLOAT lowestFrequency) { length = (long) (Stk::sampleRate() / lowestFrequency + 1); delayLine = new DelayA(0.5 * length, length); combDelay = new DelayL( 0.2 * length, length); filter = new OneZero(); noise = new Noise(); biQuad[0] = new BiQuad(); biQuad[1] = new BiQuad(); biQuad[2] = new BiQuad(); biQuad[3] = new BiQuad(); pluckAmplitude = 0.3; pickupPosition = (MY_FLOAT) 0.4; lastFrequency = lowestFrequency * 2.0; lastLength = length * 0.5; stretching = 0.9999; baseLoopGain = 0.995; loopGain = 0.999; clear(); } StifKarp :: ~StifKarp() { delete delayLine; delete combDelay; delete filter; delete noise; delete biQuad[0]; delete biQuad[1]; delete biQuad[2]; delete biQuad[3]; } void StifKarp :: clear() { delayLine->clear(); combDelay->clear(); filter->clear(); } void StifKarp :: setFrequency(MY_FLOAT frequency) { lastFrequency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): StifKarp: setFrequency parameter is less than or equal to zero!" << std::endl; lastFrequency = 220.0; } lastLength = Stk::sampleRate() / lastFrequency; MY_FLOAT delay = lastLength - 0.5; if (delay <= 0.0) delay = 0.3; else if (delay > length) delay = length; delayLine->setDelay( delay ); loopGain = baseLoopGain + (frequency * (MY_FLOAT) 0.000005); if (loopGain >= 1.0) loopGain = (MY_FLOAT) 0.99999; setStretch(stretching); combDelay->setDelay((MY_FLOAT) 0.5 * pickupPosition * lastLength); // chuck m_frequency = lastFrequency; } void StifKarp :: setStretch(MY_FLOAT stretch) { stretching = stretch; MY_FLOAT coefficient; MY_FLOAT freq = lastFrequency * 2.0; MY_FLOAT dFreq = ( (0.5 * Stk::sampleRate()) - freq ) * 0.25; MY_FLOAT temp = 0.5 + (stretch * 0.5); if (temp > 0.9999) temp = 0.9999; for (int i=0; i<4; i++) { coefficient = temp * temp; biQuad[i]->setA2( coefficient ); biQuad[i]->setB0( coefficient ); biQuad[i]->setB2( 1.0 ); coefficient = -2.0 * temp * cos(TWO_PI * freq / Stk::sampleRate()); biQuad[i]->setA1( coefficient ); biQuad[i]->setB1( coefficient ); freq += dFreq; } } void StifKarp :: setPickupPosition(MY_FLOAT position) { pickupPosition = position; if ( position < 0.0 ) { std::cerr << "[chuck](via STK): StifKarp: setPickupPosition parameter is less than zero!" << std::endl; pickupPosition = 0.0; } else if ( position > 1.0 ) { std::cerr << "[chuck](via STK): StifKarp: setPickupPosition parameter is greater than 1.0!" << std::endl; pickupPosition = 1.0; } // Set the pick position, which puts zeroes at position * length. combDelay->setDelay(0.5 * pickupPosition * lastLength); } void StifKarp :: setBaseLoopGain(MY_FLOAT aGain) { baseLoopGain = aGain; loopGain = baseLoopGain + (lastFrequency * 0.000005); if ( loopGain > 0.99999 ) loopGain = (MY_FLOAT) 0.99999; } void StifKarp :: pluck(MY_FLOAT amplitude) { MY_FLOAT gain = amplitude; if ( gain > 1.0 ) { std::cerr << "[chuck](via STK): StifKarp: pluck amplitude greater than 1.0!" << std::endl; gain = 1.0; } else if ( gain < 0.0 ) { std::cerr << "[chuck](via STK): StifKarp: pluck amplitude less than zero!" << std::endl; gain = 0.0; } pluckAmplitude = amplitude; for (long i=0; itick((delayLine->lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude); //delayLine->tick( combDelay->tick((delayLine->lastOut() * 0.6) + 0.4 * noise->tick() * pluckAmplitude)); } } void StifKarp :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { this->setFrequency(frequency); this->pluck(amplitude); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): StifKarp: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void StifKarp :: noteOff(MY_FLOAT amplitude) { MY_FLOAT gain = amplitude; if ( gain > 1.0 ) { std::cerr << "[chuck](via STK): StifKarp: noteOff amplitude greater than 1.0!" << std::endl; gain = 1.0; } else if ( gain < 0.0 ) { std::cerr << "[chuck](via STK): StifKarp: noteOff amplitude less than zero!" << std::endl; gain = 0.0; } loopGain = (1.0 - gain) * 0.5; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): StifPluck: NoteOff amplitude = " << amplitude << std::endl; #endif } MY_FLOAT StifKarp :: tick() { MY_FLOAT temp = delayLine->lastOut() * loopGain; // Calculate allpass stretching. for (int i=0; i<4; i++) temp = biQuad[i]->tick(temp); // Moving average filter. temp = filter->tick(temp); lastOutput = delayLine->tick(temp); lastOutput = lastOutput - combDelay->tick(lastOutput); return lastOutput; } void StifKarp :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): StifKarp: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): StifKarp: Control value greater than 128.0!" << std::endl; } if (number == __SK_PickPosition_) // 4 setPickupPosition( norm ); else if (number == __SK_StringDamping_) { // 11 setBaseLoopGain( 0.97 + (norm * 0.03) ); m_sustain = norm; } else if (number == __SK_StringDetune_) // 1 setStretch( 0.9 + (0.1 * (1.0 - norm)) ); else std::cerr << "[chuck](via STK): StifKarp: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): StifKarp: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Stk \brief STK base class Nearly all STK classes inherit from this class. The global sample rate can be queried and modified via Stk. In addition, this class provides error handling and byte-swapping functions. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include MY_FLOAT Stk :: srate = (MY_FLOAT) SRATE; std::string Stk :: rawwavepath = RAWWAVE_PATH; const Stk::STK_FORMAT Stk :: STK_SINT8 = 1; const Stk::STK_FORMAT Stk :: STK_SINT16 = 2; const Stk::STK_FORMAT Stk :: STK_SINT32 = 8; const Stk::STK_FORMAT Stk :: MY_FLOAT32 = 16; const Stk::STK_FORMAT Stk :: MY_FLOAT64 = 32; Stk :: Stk(void) { } Stk :: ~Stk(void) { } MY_FLOAT Stk :: sampleRate(void) { return srate; } void Stk :: setSampleRate(MY_FLOAT newRate) { if (newRate > 0) srate = newRate; } std::string Stk :: rawwavePath(void) { return rawwavepath; } void Stk :: setRawwavePath(std::string newPath) { if ( !newPath.empty() ) rawwavepath = newPath; // Make sure the path includes a "/" if ( rawwavepath[rawwavepath.length()-1] != '/' ) rawwavepath += "/"; } void Stk :: swap16(unsigned char *ptr) { register unsigned char val; // Swap 1st and 2nd bytes val = *(ptr); *(ptr) = *(ptr+1); *(ptr+1) = val; } void Stk :: swap32(unsigned char *ptr) { register unsigned char val; // Swap 1st and 4th bytes val = *(ptr); *(ptr) = *(ptr+3); *(ptr+3) = val; //Swap 2nd and 3rd bytes ptr += 1; val = *(ptr); *(ptr) = *(ptr+1); *(ptr+1) = val; } void Stk :: swap64(unsigned char *ptr) { register unsigned char val; // Swap 1st and 8th bytes val = *(ptr); *(ptr) = *(ptr+7); *(ptr+7) = val; // Swap 2nd and 7th bytes ptr += 1; val = *(ptr); *(ptr) = *(ptr+5); *(ptr+5) = val; // Swap 3rd and 6th bytes ptr += 1; val = *(ptr); *(ptr) = *(ptr+3); *(ptr+3) = val; // Swap 4th and 5th bytes ptr += 1; val = *(ptr); *(ptr) = *(ptr+1); *(ptr+1) = val; } #if (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__) || defined(__OS_WINDOWS_CYGWIN__)) #include #elif defined(__OS_WINDOWS__) #include #endif void Stk :: sleep(unsigned long milliseconds) { #if defined(__OS_WINDOWS__) Sleep((DWORD) milliseconds); #elif (defined(__OS_IRIX__) || defined(__OS_LINUX__) || defined(__OS_MACOSX__) || defined(__OS_WINDOWS_CYGWIN__)) usleep( (unsigned long) (milliseconds * 1000.0) ); #endif } void Stk :: handleError( const char *message, StkError::TYPE type ) { if (type == StkError::WARNING) fprintf(stderr, "%s\n", message); else if (type == StkError::DEBUG_WARNING) { #if defined(_STK_DEBUG_) fprintf(stderr, "%s\n", message); #endif } else { // Print error message before throwing. fprintf(stderr, "%s\n", message); throw StkError(message, type); } } StkError :: StkError(const char *p, TYPE tipe) : type(tipe) { strncpy(message, p, 256); } StkError :: ~StkError(void) { } void StkError :: printMessage(void) { printf("%s\n", message); } /***************************************************/ /*! \class SubNoise \brief STK sub-sampled noise generator. Generates a new random number every "rate" ticks using the C rand() function. The quality of the rand() function varies from one OS to another. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ SubNoise :: SubNoise(int subRate) : Noise() { rate = subRate; counter = rate; } SubNoise :: ~SubNoise() { } int SubNoise :: subRate(void) const { return rate; } void SubNoise :: setRate(int subRate) { if (subRate > 0) rate = subRate; } MY_FLOAT SubNoise :: tick() { if ( ++counter > rate ) { Noise::tick(); counter = 1; } return lastOutput; } /***************************************************/ /*! \class Table \brief STK table lookup class. This class loads a table of floating-point doubles, which are assumed to be in big-endian format. Linear interpolation is performed for fractional lookup indexes. An StkError will be thrown if the table file is not found. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include #include #include Table :: Table(char *fileName) { char message[256]; // Use the system call "stat" to determine the file length struct stat filestat; if ( stat(fileName, &filestat) == -1 ) { sprintf(message, "[chuck](via Table): Couldn't stat or find file (%s).", fileName); handleError( message, StkError::FILE_NOT_FOUND ); } length = (long) filestat.st_size / 8; // length in 8-byte samples // Open the file and read samples into data[] FILE *fd; fd = fopen(fileName,"rb"); if (!fd) { sprintf(message, "[chuck](via Table): Couldn't open or find file (%s).", fileName); handleError( message, StkError::FILE_NOT_FOUND ); } data = (MY_FLOAT *) new MY_FLOAT[length]; // Read samples into data[] long i = 0; double temp; while ( fread(&temp, 8, 1, fd) ) { if( little_endian ) swap64((unsigned char *)&temp); data[i++] = (MY_FLOAT) temp; } fclose(fd); lastOutput = 0.0; } Table :: ~Table() { delete [ ] data; } long Table :: getLength() const { return length; } MY_FLOAT Table :: lastOut() const { return lastOutput; } MY_FLOAT Table :: tick(MY_FLOAT index) { MY_FLOAT alpha; long temp; if (index > length-1) { std::cerr << "[chuck](via STK): Table: Index (" << index << ") exceeds table length ... sticking at end!" << std::endl; index = length-1; } else if (index < 0.0) { std::cerr << "[chuck](via STK): Table: Index (" << index << ") is less than zero ... setting to zero!" << std::endl; index = 0.0; } // Index in range 0 to length-1 temp = (long) index; // Integer part of index alpha = index - (MY_FLOAT) temp; // Fractional part of index if (alpha > 0.0) { // Do linear interpolation lastOutput = data[temp]; lastOutput += (alpha*(data[temp+1] - lastOutput)); } else lastOutput = data[temp]; return lastOutput; } MY_FLOAT *Table :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ TubeBell :: TubeBell() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 1.0 * 0.995); this->setRatio(1, 1.414 * 0.995); this->setRatio(2, 1.0 * 1.005); this->setRatio(3, 1.414 * 1.000); gains[0] = __FM_gains[94]; gains[1] = __FM_gains[76]; gains[2] = __FM_gains[99]; gains[3] = __FM_gains[71]; adsr[0]->setAllTimes( 0.005, 4.0, 0.0, 0.04); adsr[1]->setAllTimes( 0.005, 4.0, 0.0, 0.04); adsr[2]->setAllTimes( 0.001, 2.0, 0.0, 0.04); adsr[3]->setAllTimes( 0.004, 4.0, 0.0, 0.04); twozero->setGain( 0.5 ); vibrato->setFrequency( 2.0 ); } TubeBell :: ~TubeBell() { } void TubeBell :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[94]; gains[1] = amplitude * __FM_gains[76]; gains[2] = amplitude * __FM_gains[99]; gains[3] = amplitude * __FM_gains[71]; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "TubeBell: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT TubeBell :: tick() { MY_FLOAT temp, temp2; temp = gains[1] * adsr[1]->tick() * waves[1]->tick(); temp = temp * control1; waves[0]->addPhaseOffset(temp); waves[3]->addPhaseOffset(twozero->lastOut()); temp = gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); waves[2]->addPhaseOffset(temp); temp = ( 1.0 - (control2 * 0.5)) * gains[0] * adsr[0]->tick() * waves[0]->tick(); temp += control2 * 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick(); // Calculate amplitude modulation and apply it to output. temp2 = vibrato->tick() * modDepth; temp = temp * (1.0 + temp2); lastOutput = temp * 0.5; return lastOutput; } /***************************************************/ /*! \class TwoPole \brief STK two-pole filter class. This protected Filter subclass implements a two-pole digital filter. A method is provided for creating a resonance in the frequency response while maintaining a nearly constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include TwoPole :: TwoPole() : FilterStk() { MY_FLOAT B = 1.0; MY_FLOAT A[3] = {1.0, 0.0, 0.0}; m_resFreq = 440.0; m_resRad = 0.0; m_resNorm = false; FilterStk::setCoefficients( 1, &B, 3, A ); } TwoPole :: ~TwoPole() { } void TwoPole :: clear(void) { FilterStk::clear(); } void TwoPole :: setB0(MY_FLOAT b0) { b[0] = b0; } void TwoPole :: setA1(MY_FLOAT a1) { a[1] = a1; } void TwoPole :: setA2(MY_FLOAT a2) { a[2] = a2; } void TwoPole :: setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize) { a[2] = radius * radius; a[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * frequency / Stk::sampleRate()); if ( normalize ) { // Normalize the filter gain ... not terribly efficient. MY_FLOAT real = 1 - radius + (a[2] - radius) * cos(TWO_PI * 2 * frequency / Stk::sampleRate()); MY_FLOAT imag = (a[2] - radius) * sin(TWO_PI * 2 * frequency / Stk::sampleRate()); b[0] = sqrt( pow(real, 2) + pow(imag, 2) ); } } void TwoPole :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT TwoPole :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT TwoPole :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT TwoPole :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[0] * inputs[0] - a[2] * outputs[2] - a[1] * outputs[1]; outputs[2] = outputs[1]; outputs[1] = outputs[0]; // gewang: dedenormal CK_STK_DDN(outputs[1]); CK_STK_DDN(outputs[2]); return outputs[0]; } MY_FLOAT *TwoPole :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i TwoZero :: TwoZero() : FilterStk() { MY_FLOAT B[3] = {1.0, 0.0, 0.0}; MY_FLOAT A = 1.0; m_notchFreq = 440.0; m_notchRad = 0.0; FilterStk::setCoefficients( 3, B, 1, &A ); } TwoZero :: ~TwoZero() { } void TwoZero :: clear(void) { FilterStk::clear(); } void TwoZero :: setB0(MY_FLOAT b0) { b[0] = b0; } void TwoZero :: setB1(MY_FLOAT b1) { b[1] = b1; } void TwoZero :: setB2(MY_FLOAT b2) { b[2] = b2; } void TwoZero :: setNotch(MY_FLOAT frequency, MY_FLOAT radius) { b[2] = radius * radius; b[1] = (MY_FLOAT) -2.0 * radius * cos(TWO_PI * (double) frequency / Stk::sampleRate()); // Normalize the filter gain. if (b[1] > 0.0) // Maximum at z = 0. b[0] = 1.0 / (1.0+b[1]+b[2]); else // Maximum at z = -1. b[0] = 1.0 / (1.0-b[1]+b[2]); b[1] *= b[0]; b[2] *= b[0]; } void TwoZero :: setGain(MY_FLOAT theGain) { FilterStk::setGain(theGain); } MY_FLOAT TwoZero :: getGain(void) const { return FilterStk::getGain(); } MY_FLOAT TwoZero :: lastOut(void) const { return FilterStk::lastOut(); } MY_FLOAT TwoZero :: tick(MY_FLOAT sample) { inputs[0] = gain * sample; outputs[0] = b[2] * inputs[2] + b[1] * inputs[1] + b[0] * inputs[0]; inputs[2] = inputs[1]; inputs[1] = inputs[0]; return outputs[0]; } MY_FLOAT *TwoZero :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i Vector3D :: Vector3D(double initX, double initY, double initZ) { myX = initX; myY = initY; myZ = initZ; } Vector3D :: ~Vector3D() { } double Vector3D :: getX() { return myX; } double Vector3D :: getY() { return myY; } double Vector3D :: getZ() { return myZ; } double Vector3D :: getLength() { double temp; temp = myX * myX; temp += myY * myY; temp += myZ * myZ; temp = sqrt(temp); return temp; } void Vector3D :: setXYZ(double anX, double aY, double aZ) { myX = anX; myY = aY; myZ = aZ; }; void Vector3D :: setX(double aval) { myX = aval; } void Vector3D :: setY(double aval) { myY = aval; } void Vector3D :: setZ(double aval) { myZ = aval; } /***************************************************/ /*! \class VoicForm \brief Four formant synthesis instrument. This instrument contains an excitation singing wavetable (looping wave with random and periodic vibrato, smoothing on frequency, etc.), excitation noise, and four sweepable complex resonances. Measured formant data is included, and enough data is there to support either parallel or cascade synthesis. In the floating point case cascade synthesis is the most natural so that's what you'll find here. Control Change Numbers: - Voiced/Unvoiced Mix = 2 - Vowel/Phoneme Selection = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Loudness (Spectral Tilt) = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include VoicForm :: VoicForm() : Instrmnt() { // Concatenate the STK rawwave path to the rawwave file voiced = new SingWave( "special:impuls20", TRUE ); voiced->setGainRate( 0.001 ); voiced->setGainTarget( 0.0 ); noise = new Noise; for ( int i=0; i<4; i++ ) { filters[i] = new FormSwep; filters[i]->setSweepRate( 0.001 ); } onezero = new OneZero; onezero->setZero( -0.9 ); onepole = new OnePole; onepole->setPole( 0.9 ); noiseEnv = new Envelope; noiseEnv->setRate( 0.001 ); noiseEnv->setTarget( 0.0 ); m_phonemeNum = 0; this->setPhoneme( "eee" ); this->clear(); // chuck setFrequency( 440 ); } VoicForm :: ~VoicForm() { delete voiced; delete noise; delete onezero; delete onepole; delete noiseEnv; for ( int i=0; i<4; i++ ) { delete filters[i]; } } void VoicForm :: clear() { onezero->clear(); onepole->clear(); for ( int i=0; i<4; i++ ) { filters[i]->clear(); } } void VoicForm :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency; if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): VoicForm: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } voiced->setFrequency( freakency ); // chuck m_frequency = freakency; } bool VoicForm :: setPhoneme( const char *phoneme ) { bool found = false; unsigned int i = 0; while( i < 32 && !found ) { if( !strcmp( Phonemes::name(i), phoneme ) ) { found = true; filters[0]->setTargets( Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) ); filters[1]->setTargets( Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) ); filters[2]->setTargets( Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) ); filters[3]->setTargets( Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) ); setVoiced( Phonemes::voiceGain( i ) ); setUnVoiced( Phonemes::noiseGain( i ) ); m_phonemeNum = i; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): VoicForm: found formant " << phoneme << " (number " << i << ")" << std::endl; #endif } i++; } if( !found ) std::cerr << "[chuck](via STK): VoicForm: phoneme " << phoneme << " not found!" << std::endl; else str_phoneme.str = Phonemes::name( m_phonemeNum ); return found; } void VoicForm :: setVoiced(MY_FLOAT vGain) { voiced->setGainTarget(vGain); } void VoicForm :: setUnVoiced(MY_FLOAT nGain) { noiseEnv->setTarget(nGain * 0.01); } void VoicForm :: setFilterSweepRate(int whichOne, MY_FLOAT rate) { if ( whichOne < 0 || whichOne > 3 ) { std::cerr << "[chuck](via STK): VoicForm: setFilterSweepRate filter argument outside range 0-3!" << std::endl; return; } filters[whichOne]->setSweepRate(rate); } void VoicForm :: setPitchSweepRate(MY_FLOAT rate) { voiced->setSweepRate(rate); } void VoicForm :: speak() { voiced->noteOn(); } void VoicForm :: quiet() { voiced->noteOff(); noiseEnv->setTarget( 0.0 ); } void VoicForm :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { // chuck if( frequency != m_frequency ) setFrequency(frequency); voiced->setGainTarget(amplitude); onepole->setPole( 0.97 - (amplitude * 0.2) ); } void VoicForm :: noteOn( MY_FLOAT amplitude ) { voiced->setGainTarget(amplitude); onepole->setPole( 0.97 - (amplitude * 0.2) ); } void VoicForm :: noteOff(MY_FLOAT amplitude) { this->quiet(); } MY_FLOAT VoicForm :: tick() { MY_FLOAT temp; temp = onepole->tick( onezero->tick( voiced->tick() ) ); temp += noiseEnv->tick() * noise->tick(); lastOutput = filters[0]->tick(temp); lastOutput += filters[1]->tick(temp); lastOutput += filters[2]->tick(temp); lastOutput += filters[3]->tick(temp); /* temp += noiseEnv->tick() * noise->tick(); lastOutput = filters[0]->tick(temp); lastOutput = filters[1]->tick(lastOutput); lastOutput = filters[2]->tick(lastOutput); lastOutput = filters[3]->tick(lastOutput); */ return lastOutput; } void VoicForm :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): VoicForm: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): VoicForm: Control value greater than 128.0!" << std::endl; } if (number == __SK_Breath_) { // 2 this->setVoiced( 1.0 - norm ); this->setUnVoiced( norm ); } else if (number == __SK_FootControl_) { // 4 MY_FLOAT temp = 0.0; unsigned int i = (int) value; if (i < 32) { temp = 0.9; } else if (i < 64) { i -= 32; temp = 1.0; } else if (i < 96) { i -= 64; temp = 1.1; } else if (i < 128) { i -= 96; temp = 1.2; } else if (i == 128) { i = 0; temp = 1.4; } filters[0]->setTargets( temp * Phonemes::formantFrequency(i, 0), Phonemes::formantRadius(i, 0), pow(10.0, Phonemes::formantGain(i, 0 ) / 20.0) ); filters[1]->setTargets( temp * Phonemes::formantFrequency(i, 1), Phonemes::formantRadius(i, 1), pow(10.0, Phonemes::formantGain(i, 1 ) / 20.0) ); filters[2]->setTargets( temp * Phonemes::formantFrequency(i, 2), Phonemes::formantRadius(i, 2), pow(10.0, Phonemes::formantGain(i, 2 ) / 20.0) ); filters[3]->setTargets( temp * Phonemes::formantFrequency(i, 3), Phonemes::formantRadius(i, 3), pow(10.0, Phonemes::formantGain(i, 3 ) / 20.0) ); setVoiced( Phonemes::voiceGain( i ) ); setUnVoiced( Phonemes::noiseGain( i ) ); } else if (number == __SK_ModFrequency_) // 11 voiced->setVibratoRate( norm * 12.0); // 0 to 12 Hz else if (number == __SK_ModWheel_) // 1 voiced->setVibratoGain( norm * 0.2); else if (number == __SK_AfterTouch_Cont_) { // 128 setVoiced( norm ); onepole->setPole( 0.97 - ( norm * 0.2) ); } else std::cerr << "[chuck](via STK): VoicForm: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): VoicForm: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Voicer \brief STK voice manager class. This class can be used to manage a group of STK instrument classes. Individual voices can be controlled via unique note tags. Instrument groups can be controlled by channel number. A previously constructed STK instrument class is linked with a voice manager using the addInstrument() function. An optional channel number argument can be specified to the addInstrument() function as well (default channel = 0). The voice manager does not delete any instrument instances ... it is the responsibility of the user to allocate and deallocate all instruments. The tick() function returns the mix of all sounding voices. Each noteOn returns a unique tag (credits to the NeXT MusicKit), so you can send control changes to specific voices within an ensemble. Alternately, control changes can be sent to all voices on a given channel. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include Voicer :: Voicer( int maxInstruments, MY_FLOAT decayTime ) { nVoices = 0; maxVoices = maxInstruments; voices = (Voice *) new Voice[maxVoices]; tags = 23456; muteTime = (int) ( decayTime * Stk::sampleRate() ); } Voicer :: ~Voicer() { delete [] voices; } void Voicer :: addInstrument( Instrmnt *instrument, int channel ) { //voices = (Voice *) realloc( (void *) voices, nVoices+1 * sizeof( Voice ) ); if ( nVoices == maxVoices ) { std::cerr << "[chuck](via STK): Voicer: Maximum number of voices already added!!" << std::endl; return; } voices[nVoices].instrument = instrument; voices[nVoices].tag = 0; voices[nVoices].channel = channel; voices[nVoices].noteNumber = -1; voices[nVoices].frequency = 0.0; voices[nVoices].sounding = 0; nVoices++; } void Voicer :: removeInstrument( Instrmnt *instrument ) { bool found = false; for ( int i=0; inoteOn( frequency, amplitude * ONE_OVER_128 ); voices[i].sounding = 1; return voices[i].tag; } } // All voices are sounding, so interrupt the oldest voice. int voice = -1; for ( i=0; i= 0 ) { voices[voice].tag = tags++; voices[voice].channel = channel; voices[voice].noteNumber = noteNumber; voices[voice].frequency = frequency; voices[voice].instrument->noteOn( frequency, amplitude * ONE_OVER_128 ); voices[voice].sounding = 1; return voices[voice].tag; } return -1; } void Voicer :: noteOff( MY_FLOAT noteNumber, MY_FLOAT amplitude, int channel ) { for ( int i=0; inoteOff( amplitude * ONE_OVER_128 ); voices[i].sounding = -muteTime; } } } void Voicer :: noteOff( long tag, MY_FLOAT amplitude ) { for ( int i=0; inoteOff( amplitude * ONE_OVER_128 ); voices[i].sounding = -muteTime; break; } } } void Voicer :: setFrequency( MY_FLOAT noteNumber, int channel ) { MY_FLOAT frequency = (MY_FLOAT) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 ); for ( int i=0; isetFrequency( frequency ); } } } void Voicer :: setFrequency( long tag, MY_FLOAT noteNumber ) { MY_FLOAT frequency = (MY_FLOAT) 220.0 * pow( 2.0, (noteNumber - 57.0) / 12.0 ); for ( int i=0; isetFrequency( frequency ); break; } } } void Voicer :: pitchBend( MY_FLOAT value, int channel ) { MY_FLOAT pitchScaler; if ( value < 64.0 ) pitchScaler = pow(0.5, (64.0-value)/64.0); else pitchScaler = pow(2.0, (value-64.0)/64.0); for ( int i=0; isetFrequency( (MY_FLOAT) (voices[i].frequency * pitchScaler) ); } } void Voicer :: pitchBend( long tag, MY_FLOAT value ) { MY_FLOAT pitchScaler; if ( value < 64.0 ) pitchScaler = pow(0.5, (64.0-value)/64.0); else pitchScaler = pow(2.0, (value-64.0)/64.0); for ( int i=0; isetFrequency( (MY_FLOAT) (voices[i].frequency * pitchScaler) ); break; } } } void Voicer :: controlChange( int number, MY_FLOAT value, int channel ) { for ( int i=0; icontrolChange( number, value ); } } void Voicer :: controlChange( long tag, int number, MY_FLOAT value ) { for ( int i=0; icontrolChange( number, value ); break; } } } void Voicer :: silence( void ) { for ( int i=0; i 0 ) voices[i].instrument->noteOff( 0.5 ); } } MY_FLOAT Voicer :: tick() { lastOutput = lastOutputLeft = lastOutputRight = 0.0; for ( int i=0; itick(); lastOutputLeft += voices[i].instrument->lastOutLeft(); lastOutputRight += voices[i].instrument->lastOutRight(); } if ( voices[i].sounding < 0 ) { voices[i].sounding++; if ( voices[i].sounding == 0 ) voices[i].noteNumber = -1; } } return lastOutput / nVoices; } MY_FLOAT *Voicer :: tick(MY_FLOAT *vec, unsigned int vectorSize) { for (unsigned int i=0; i WaveLoop :: WaveLoop( const char *fileName, bool raw, bool generate ) : WvIn( fileName, raw ), phaseOffset(0.0) { m_freq = 0; // If at end of file, redo extra sample frame for looping. if (chunkPointer+bufferSize == fileSize) { for (unsigned int j=0; j= fileSize) time -= fileSize; } void WaveLoop :: addPhase(MY_FLOAT anAngle) { // Add a time in cycles (one cycle = fileSize). time += fileSize * anAngle; while (time < 0.0) time += fileSize; while (time >= fileSize) time -= fileSize; } void WaveLoop :: addPhaseOffset(MY_FLOAT anAngle) { // Add a phase offset in cycles, where 1.0 = fileSize. phaseOffset = fileSize * anAngle; } const MY_FLOAT *WaveLoop :: tickFrame(void) { register MY_FLOAT tyme, alpha; register unsigned long i, index; // Check limits of time address ... if necessary, recalculate modulo fileSize. while (time < 0.0) time += fileSize; while (time >= fileSize) time -= fileSize; if (phaseOffset) { tyme = time + phaseOffset; while (tyme < 0.0) tyme += fileSize; while (tyme >= fileSize) tyme -= fileSize; } else { tyme = time; } if (chunking) { // Check the time address vs. our current buffer limits. if ( (tyme < chunkPointer) || (tyme >= chunkPointer+bufferSize) ) this->readData((long) tyme); // Adjust index for the current buffer. tyme -= chunkPointer; } // Always do linear interpolation here ... integer part of time address. index = (unsigned long) tyme; // Fractional part of time address. alpha = tyme - (MY_FLOAT) index; index *= channels; for (i=0; i #include #define CAN_RADIUS 100 #define PEA_RADIUS 30 #define BUMP_RADIUS 5 #define NORM_CAN_LOSS 0.97 #define SLOW_CAN_LOSS 0.90 #define GRAVITY 20.0 // GRAVITY WAS 6.0 #define NORM_TICK_SIZE 0.004 #define SLOW_TICK_SIZE 0.0001 #define ENV_RATE 0.001 Whistle :: Whistle() { tempVector = new Vector3D(0,0,0); can = new Sphere(CAN_RADIUS); pea = new Sphere(PEA_RADIUS); bumper = new Sphere(BUMP_RADIUS); // Concatenate the STK rawwave path to the rawwave file sine = new WaveLoop( "special:sinewave", TRUE ); sine->setFrequency(2800.0); can->setPosition(0, 0, 0); // set can location can->setVelocity(0, 0, 0); // and the velocity onepole.setPole(0.95); // 0.99 bumper->setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0); bumper->setPosition(0.0, CAN_RADIUS-BUMP_RADIUS, 0); pea->setPosition(0, CAN_RADIUS/2, 0); pea->setVelocity(35, 15, 0); envelope.setRate(ENV_RATE); envelope.keyOn(); fippleFreqMod = 0.5; fippleGainMod = 0.5; blowFreqMod = 0.25; noiseGain = 0.125; maxPressure = (MY_FLOAT) 0.0; baseFrequency = 2000; tickSize = NORM_TICK_SIZE; canLoss = NORM_CAN_LOSS; subSample = 1; subSampCount = subSample; } Whistle :: ~Whistle() { delete tempVector; delete can; delete pea; delete bumper; delete sine; } void Whistle :: clear() { } void Whistle :: setFrequency(MY_FLOAT frequency) { MY_FLOAT freakency = frequency * 4; // the whistle is a transposing instrument if ( frequency <= 0.0 ) { std::cerr << "[chuck](via STK): Whistle: setFrequency parameter is less than or equal to zero!" << std::endl; freakency = 220.0; } baseFrequency = freakency; } void Whistle :: startBlowing(MY_FLOAT amplitude, MY_FLOAT rate) { envelope.setRate(ENV_RATE); envelope.setTarget(amplitude); } void Whistle :: stopBlowing(MY_FLOAT rate) { envelope.setRate(rate); envelope.keyOff(); } void Whistle :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { setFrequency(frequency); startBlowing(amplitude*2.0 ,amplitude * 0.2); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Whistle: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << std::endl; #endif } void Whistle :: noteOff(MY_FLOAT amplitude) { this->stopBlowing(amplitude * 0.02); #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Whistle: NoteOff amplitude = " << amplitude << std::endl; #endif } int frameCount = 0; MY_FLOAT Whistle :: tick() { MY_FLOAT soundMix, tempFreq; double envOut = 0, temp, temp1, temp2, tempX, tempY; double phi, cosphi, sinphi; double gain = 0.5, mod = 0.0; if (--subSampCount <= 0) { tempVectorP = pea->getPosition(); subSampCount = subSample; temp = bumper->isInside(tempVectorP); #ifdef WHISTLE_ANIMATION frameCount += 1; if (frameCount >= (1470 / subSample)) { frameCount = 0; // printf("%f %f %f\n",tempVectorP->getX(),tempVectorP->getY(),envOut); fflush(stdout); } #endif envOut = envelope.tick(); if (temp < (BUMP_RADIUS + PEA_RADIUS)) { tempX = envOut * tickSize * 2000 * noise.tick(); tempY = -envOut * tickSize * 1000 * (1.0 + noise.tick()); pea->addVelocity(tempX,tempY,0); pea->tick(tickSize); } mod = exp(-temp * 0.01); // exp. distance falloff of fipple/pea effect temp = onepole.tick(mod); // smooth it a little gain = (1.0 - (fippleGainMod*0.5)) + (2.0 * fippleGainMod * temp); gain *= gain; // squared distance/gain // tempFreq = 1.0 // Normalized Base Freq // + (fippleFreqMod * 0.25) - (fippleFreqMod * temp) // fippleModulation // - (blowFreqMod) + (blowFreqMod * envOut); // blowingModulation // short form of above tempFreq = 1.0 + fippleFreqMod*(0.25-temp) + blowFreqMod*(envOut-1.0); tempFreq *= baseFrequency; sine->setFrequency(tempFreq); tempVectorP = pea->getPosition(); temp = can->isInside(tempVectorP); temp = -temp; // We know (hope) it's inside, just how much?? if (temp < (PEA_RADIUS * 1.25)) { pea->getVelocity(tempVector); // This is the can/pea collision tempX = tempVectorP->getX(); // calculation. Could probably tempY = tempVectorP->getY(); // simplify using tables, etc. phi = -atan2(tempY,tempX); cosphi = cos(phi); sinphi = sin(phi); temp1 = (cosphi*tempVector->getX()) - (sinphi*tempVector->getY()); temp2 = (sinphi*tempVector->getX()) + (cosphi*tempVector->getY()); temp1 = -temp1; tempX = (cosphi*temp1) + (sinphi*temp2); tempY = (-sinphi*temp1) + (cosphi*temp2); pea->setVelocity(tempX, tempY, 0); pea->tick(tickSize); pea->setVelocity(tempX*canLoss, tempY*canLoss, 0); pea->tick(tickSize); } temp = tempVectorP->getLength(); if (temp > 0.01) { tempX = tempVectorP->getX(); tempY = tempVectorP->getY(); phi = atan2(tempY,tempX); phi += 0.3 * temp / CAN_RADIUS; cosphi = cos(phi); sinphi = sin(phi); tempX = 3.0 * temp * cosphi; tempY = 3.0 * temp * sinphi; } else { tempX = 0.0; tempY = 0.0; } temp = (0.9 + 0.1*subSample*noise.tick()) * envOut * 0.6 * tickSize; pea->addVelocity(temp * tempX, (temp*tempY) - (GRAVITY*tickSize),0); pea->tick(tickSize); // bumper->tick(0.0); } temp = envOut * envOut * gain / 2; soundMix = temp * (sine->tick() + (noiseGain*noise.tick())); lastOutput = 0.25 * soundMix; // should probably do one-zero filter here return lastOutput; } void Whistle :: controlChange(int number, MY_FLOAT value) { MY_FLOAT norm = value * ONE_OVER_128; if ( norm < 0 ) { norm = 0.0; std::cerr << "[chuck](via STK): Whistle: Control value less than zero!" << std::endl; } else if ( norm > 1.0 ) { norm = 1.0; std::cerr << "[chuck](via STK): Whistle: Control value greater than 128.0!" << std::endl; } if (number == __SK_NoiseLevel_) // 4 noiseGain = 0.25 * norm; else if (number == __SK_ModFrequency_) // 11 fippleFreqMod = norm; else if (number == __SK_ModWheel_) // 1 fippleGainMod = norm; else if (number == __SK_AfterTouch_Cont_) // 128 envelope.setTarget( norm * 2.0 ); else if (number == __SK_Breath_) // 2 blowFreqMod = norm * 0.5; else if (number == __SK_Sustain_) // 64 if (value < 1.0) subSample = 1; else std::cerr << "[chuck](via STK): Whistle: Undefined Control Number (" << number << ")!!" << std::endl; #if defined(_STK_DEBUG_) std::cerr << "[chuck](via STK): Whistle: controlChange number = " << number << ", value = " << value << std::endl; #endif } /***************************************************/ /*! \class Wurley \brief STK Wurlitzer electric piano FM synthesis instrument. This class implements two simple FM Pairs summed together, also referred to as algorithm 5 of the TX81Z. \code Algorithm 5 is : 4->3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ Wurley :: Wurley() : FM() { // Concatenate the STK rawwave path to the rawwave files for ( int i=0; i<3; i++ ) waves[i] = new WaveLoop( "special:sinewave", TRUE ); waves[3] = new WaveLoop( "special:fwavblnk", TRUE ); this->setRatio(0, 1.0); this->setRatio(1, 4.0); this->setRatio(2, -510.0); this->setRatio(3, -510.0); gains[0] = __FM_gains[99]; gains[1] = __FM_gains[82]; gains[2] = __FM_gains[92]; gains[3] = __FM_gains[68]; adsr[0]->setAllTimes( 0.001, 1.50, 0.0, 0.04); adsr[1]->setAllTimes( 0.001, 1.50, 0.0, 0.04); adsr[2]->setAllTimes( 0.001, 0.25, 0.0, 0.04); adsr[3]->setAllTimes( 0.001, 0.15, 0.0, 0.04); twozero->setGain( 2.0 ); vibrato->setFrequency( 8.0 ); } Wurley :: ~Wurley() { } void Wurley :: setFrequency(MY_FLOAT frequency) { baseFrequency = frequency; waves[0]->setFrequency(baseFrequency * ratios[0]); waves[1]->setFrequency(baseFrequency * ratios[1]); waves[2]->setFrequency(ratios[2]); // Note here a 'fixed resonance'. waves[3]->setFrequency(ratios[3]); // chuck m_frequency = baseFrequency; } void Wurley :: noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) { gains[0] = amplitude * __FM_gains[99]; gains[1] = amplitude * __FM_gains[82]; gains[2] = amplitude * __FM_gains[82]; gains[3] = amplitude * __FM_gains[68]; this->setFrequency(frequency); this->keyOn(); #if defined(_STK_DEBUG_) cerr << "Wurley: NoteOn frequency = " << frequency << ", amplitude = " << amplitude << endl; #endif } MY_FLOAT Wurley :: tick() { MY_FLOAT temp, temp2; temp = gains[1] * adsr[1]->tick() * waves[1]->tick(); temp = temp * control1; waves[0]->addPhaseOffset(temp); waves[3]->addPhaseOffset(twozero->lastOut()); temp = gains[3] * adsr[3]->tick() * waves[3]->tick(); twozero->tick(temp); waves[2]->addPhaseOffset(temp); temp = ( 1.0 - (control2 * 0.5)) * gains[0] * adsr[0]->tick() * waves[0]->tick(); temp += control2 * 0.5 * gains[2] * adsr[2]->tick() * waves[2]->tick(); // Calculate amplitude modulation and apply it to output. temp2 = vibrato->tick() * modDepth; temp = temp * (1.0 + temp2); lastOutput = temp * 0.5; return lastOutput; } // CHUCK HACK: void Wurley :: controlChange( int which, MY_FLOAT value ) { if( which == 3 ) { adsr[0]->setAllTimes( 0.001, 1.50 * value, 0.0, 0.04); adsr[1]->setAllTimes( 0.001, 1.50 * value, 0.0, 0.04); adsr[2]->setAllTimes( 0.001, 0.25 * value, 0.0, 0.04); adsr[3]->setAllTimes( 0.001, 0.15 * value, 0.0, 0.04); } else { // call parent FM::controlChange( which, value ); } } /***************************************************/ /*! \class WvIn \brief STK audio data input base class. This class provides input support for various audio file formats. It also serves as a base class for "realtime" streaming subclasses. WvIn loads the contents of an audio file for subsequent output. Linear interpolation is used for fractional "read rates". WvIn supports multi-channel data in interleaved format. It is important to distinguish the tick() methods, which return samples produced by averaging across sample frames, from the tickFrame() methods, which return pointers to multi-channel sample frames. For single-channel data, these methods return equivalent values. Small files are completely read into local memory during instantiation. Large files are read incrementally from disk. The file size threshold and the increment size values are defined in WvIn.h. WvIn currently supports WAV, AIFF, SND (AU), MAT-file (Matlab), and STK RAW file formats. Signed integer (8-, 16-, and 32-bit) and floating- point (32- and 64-bit) data types are supported. Uncompressed data types are not supported. If using MAT-files, data should be saved in an array with each data channel filling a matrix row. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #include #include #include #include #include #include "util_raw.h" WvIn :: WvIn() { init(); } WvIn :: WvIn( const char *fileName, bool raw, bool doNormalize, bool generate ) { init(); openFile( fileName, raw, generate ); } WvIn :: ~WvIn() { if (fd) fclose(fd); if (data) delete [] data; if (lastOutput) delete [] lastOutput; m_loaded = false; } void WvIn :: init( void ) { fd = 0; m_loaded = false; // strcpy ( m_filename, "" ); data = 0; lastOutput = 0; chunking = false; finished = true; interpolate = false; bufferSize = 0; channels = 0; time = 0.0; } void WvIn :: closeFile( void ) { if ( fd ) fclose( fd ); finished = true; str_filename.str = ""; } void WvIn :: openFile( const char *fileName, bool raw, bool doNormalize, bool generate ) { unsigned long lastChannels = channels; unsigned long samples, lastSamples = (bufferSize+1)*channels; str_filename.str = fileName; //strncpy ( m_filename, fileName, 255 ); //m_filename[255] = '\0'; if(!generate || !strstr(fileName, "special:")) { closeFile(); // Try to open the file. fd = fopen(fileName, "rb"); if (!fd) { sprintf(msg, "[chuck](via WvIn): Could not open or find file (%s).", fileName); handleError(msg, StkError::FILE_NOT_FOUND); } bool result = false; if ( raw ) result = getRawInfo( fileName ); else { char header[12]; if ( fread(&header, 4, 3, fd) != 3 ) goto error; if ( !strncmp(header, "RIFF", 4) && !strncmp(&header[8], "WAVE", 4) ) result = getWavInfo( fileName ); else if ( !strncmp(header, ".snd", 4) ) result = getSndInfo( fileName ); else if ( !strncmp(header, "FORM", 4) && (!strncmp(&header[8], "AIFF", 4) || !strncmp(&header[8], "AIFC", 4) ) ) result = getAifInfo( fileName ); else { if ( fseek(fd, 126, SEEK_SET) == -1 ) goto error; if ( fread(&header, 2, 1, fd) != 1 ) goto error; if (!strncmp(header, "MI", 2) || !strncmp(header, "IM", 2) ) result = getMatInfo( fileName ); else { raw = TRUE; result = getRawInfo( fileName ); // sprintf(msg, "WvIn: File (%s) format unknown.", fileName); // handleError(msg, StkError::FILE_UNKNOWN_FORMAT); } } } if ( result == false ) handleError(msg, StkError::FILE_ERROR); if ( fileSize == 0 ) { sprintf(msg, "[chuck](via WvIn): File (%s) data size is zero!", fileName); handleError(msg, StkError::FILE_ERROR); } } else { bufferSize = 256; channels = 1; } // Allocate new memory if necessary. samples = (bufferSize+1)*channels; if ( lastSamples < samples ) { if ( data ) delete [] data; data = (MY_FLOAT *) new MY_FLOAT[samples]; } if ( lastChannels < channels ) { if ( lastOutput ) delete [] lastOutput; lastOutput = (MY_FLOAT *) new MY_FLOAT[channels]; } if ( fmod(rate, 1.0) != 0.0 ) interpolate = true; chunkPointer = 0; reset(); if(generate && strstr(fileName, "special:")) { // STK rawwave files have no header and are assumed to contain a // monophonic stream of 16-bit signed integers in big-endian byte // order with a sample rate of 22050 Hz. fileSize = bufferSize; dataOffset = 0; interpolate = true; chunking = false; dataType = STK_SINT16; byteswap = false; fileRate = 22050.0; rate = (MY_FLOAT)fileRate / Stk::sampleRate(); // which if( strstr(fileName, "special:sinewave") ) { for (unsigned int j=0; j CHUNK_THRESHOLD) { chunking = true; bufferSize = CHUNK_SIZE; gain = 1.0 / 32768.0; } // STK rawwave files have no header and are assumed to contain a // monophonic stream of 16-bit signed integers in big-endian byte // order with a sample rate of 22050 Hz. channels = 1; dataOffset = 0; rate = (MY_FLOAT) 22050.0 / Stk::sampleRate(); fileRate = 22050.0; interpolate = false; dataType = STK_SINT16; byteswap = false; if( little_endian ) byteswap = true; return true; } bool WvIn :: getWavInfo( const char *fileName ) { // Find "format" chunk ... it must come before the "data" chunk. char id[4]; SINT32 chunkSize; if ( fread(&id, 4, 1, fd) != 1 ) goto error; while ( strncmp(id, "fmt ", 4) ) { if ( fread(&chunkSize, 4, 1, fd) != 1 ) goto error; if( !little_endian ) swap32((unsigned char *)&chunkSize); if ( fseek(fd, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd) != 1 ) goto error; } // Check that the data is not compressed. SINT16 format_tag; if ( fread(&chunkSize, 4, 1, fd) != 1 ) goto error; // Read fmt chunk size. if ( fread(&format_tag, 2, 1, fd) != 1 ) goto error; if( !little_endian ) { swap16((unsigned char *)&format_tag); swap32((unsigned char *)&chunkSize); } if (format_tag != 1 && format_tag != 3 ) { // PCM = 1, FLOAT = 3 sprintf(msg, "[chuck](via WvIn): %s contains an unsupported data format type (%d).", fileName, format_tag); return false; } // Get number of channels from the header. SINT16 temp; if ( fread(&temp, 2, 1, fd) != 1 ) goto error; if( !little_endian ) swap16((unsigned char *)&temp); channels = (unsigned int ) temp; // Get file sample rate from the header. SINT32 srate; if ( fread(&srate, 4, 1, fd) != 1 ) goto error; if( !little_endian ) swap32((unsigned char *)&srate); fileRate = (MY_FLOAT) srate; // Set default rate based on file sampling rate. rate = (MY_FLOAT) ( srate / Stk::sampleRate() ); // Determine the data type. dataType = 0; if ( fseek(fd, 6, SEEK_CUR) == -1 ) goto error; // Locate bits_per_sample info. if ( fread(&temp, 2, 1, fd) != 1 ) goto error; if( !little_endian ) swap16((unsigned char *)&temp); if ( format_tag == 1 ) { if (temp == 8) dataType = STK_SINT8; else if (temp == 16) dataType = STK_SINT16; else if (temp == 32) dataType = STK_SINT32; } else if ( format_tag == 3 ) { if (temp == 32) dataType = MY_FLOAT32; else if (temp == 64) dataType = MY_FLOAT64; } if ( dataType == 0 ) { sprintf(msg, "[chuck](via WvIn): %d bits per sample with data format %d are not supported (%s).", temp, format_tag, fileName); return false; } // Jump over any remaining part of the "fmt" chunk. if ( fseek(fd, chunkSize-16, SEEK_CUR) == -1 ) goto error; // Find "data" chunk ... it must come after the "fmt" chunk. if ( fread(&id, 4, 1, fd) != 1 ) goto error; while ( strncmp(id, "data", 4) ) { if ( fread(&chunkSize, 4, 1, fd) != 1 ) goto error; if( !little_endian ) swap32((unsigned char *)&chunkSize); if ( fseek(fd, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd) != 1 ) goto error; } // Get length of data from the header. SINT32 bytes; if ( fread(&bytes, 4, 1, fd) != 1 ) goto error; if( !little_endian ) swap32((unsigned char *)&bytes); fileSize = 8 * bytes / temp / channels; // sample frames bufferSize = fileSize; if (fileSize > CHUNK_THRESHOLD) { chunking = true; bufferSize = CHUNK_SIZE; } dataOffset = ftell(fd); byteswap = false; if( !little_endian ) byteswap = true; return true; error: sprintf(msg, "[chuck](via WvIn): Error reading WAV file (%s).", fileName); return false; } bool WvIn :: getSndInfo( const char *fileName ) { // Determine the data type. SINT32 format; if ( fseek(fd, 12, SEEK_SET) == -1 ) goto error; // Locate format if ( fread(&format, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&format); if (format == 2) dataType = STK_SINT8; else if (format == 3) dataType = STK_SINT16; else if (format == 5) dataType = STK_SINT32; else if (format == 6) dataType = MY_FLOAT32; else if (format == 7) dataType = MY_FLOAT64; else { sprintf(msg, "[chuck](via WvIn): data format in file %s is not supported.", fileName); return false; } // Get file sample rate from the header. SINT32 srate; if ( fread(&srate, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&srate); fileRate = (MY_FLOAT) srate; // Set default rate based on file sampling rate. rate = (MY_FLOAT) ( srate / sampleRate() ); // Get number of channels from the header. SINT32 chans; if ( fread(&chans, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&chans); channels = chans; if ( fseek(fd, 4, SEEK_SET) == -1 ) goto error; if ( fread(&dataOffset, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&dataOffset); // Get length of data from the header. if ( fread(&fileSize, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&fileSize); fileSize /= 2 * channels; // Convert to sample frames. bufferSize = fileSize; if (fileSize > CHUNK_THRESHOLD) { chunking = true; bufferSize = CHUNK_SIZE; } byteswap = false; if( little_endian ) byteswap = true; return true; error: sprintf(msg, "[chuck](via WvIn): Error reading SND file (%s).", fileName); return false; } bool WvIn :: getAifInfo( const char *fileName ) { bool aifc = false; char id[4]; // Determine whether this is AIFF or AIFC. if ( fseek(fd, 8, SEEK_SET) == -1 ) goto error; if ( fread(&id, 4, 1, fd) != 1 ) goto error; if ( !strncmp(id, "AIFC", 4) ) aifc = true; // Find "common" chunk SINT32 chunkSize; if ( fread(&id, 4, 1, fd) != 1) goto error; while ( strncmp(id, "COMM", 4) ) { if ( fread(&chunkSize, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&chunkSize); if ( fseek(fd, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd) != 1 ) goto error; } // Get number of channels from the header. SINT16 temp; if ( fseek(fd, 4, SEEK_CUR) == -1 ) goto error; // Jump over chunk size if ( fread(&temp, 2, 1, fd) != 1 ) goto error; if( little_endian ) swap16((unsigned char *)&temp); channels = temp; // Get length of data from the header. SINT32 frames; if ( fread(&frames, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&frames); fileSize = frames; // sample frames bufferSize = fileSize; if (fileSize > CHUNK_THRESHOLD) { chunking = true; bufferSize = CHUNK_SIZE; } // Read the number of bits per sample. if ( fread(&temp, 2, 1, fd) != 1 ) goto error; if( little_endian ) swap16((unsigned char *)&temp); // Get file sample rate from the header. For AIFF files, this value // is stored in a 10-byte, IEEE Standard 754 floating point number, // so we need to convert it first. unsigned char srate[10]; unsigned char exp; unsigned long mantissa; unsigned long last; if ( fread(&srate, 10, 1, fd) != 1 ) goto error; mantissa = (unsigned long) *(unsigned long *)(srate+2); if( little_endian ) swap32((unsigned char *)&mantissa); exp = 30 - *(srate+1); last = 0; while (exp--) { last = mantissa; mantissa >>= 1; } if (last & 0x00000001) mantissa++; fileRate = (MY_FLOAT) mantissa; // Set default rate based on file sampling rate. rate = (MY_FLOAT) ( fileRate / sampleRate() ); // Determine the data format. dataType = 0; if ( aifc == false ) { if ( temp == 8 ) dataType = STK_SINT8; else if ( temp == 16 ) dataType = STK_SINT16; else if ( temp == 32 ) dataType = STK_SINT32; } else { if ( fread(&id, 4, 1, fd) != 1 ) goto error; if ( (!strncmp(id, "fl32", 4) || !strncmp(id, "FL32", 4)) && temp == 32 ) dataType = MY_FLOAT32; else if ( (!strncmp(id, "fl64", 4) || !strncmp(id, "FL64", 4)) && temp == 64 ) dataType = MY_FLOAT64; } if ( dataType == 0 ) { sprintf(msg, "[chuck](via WvIn): %d bits per sample in file %s are not supported.", temp, fileName); return false; } // Start at top to find data (SSND) chunk ... chunk order is undefined. if ( fseek(fd, 12, SEEK_SET) == -1 ) goto error; // Find data (SSND) chunk if ( fread(&id, 4, 1, fd) != 1 ) goto error; while ( strncmp(id, "SSND", 4) ) { if ( fread(&chunkSize, 4, 1, fd) != 1 ) goto error; if( little_endian ) swap32((unsigned char *)&chunkSize); if ( fseek(fd, chunkSize, SEEK_CUR) == -1 ) goto error; if ( fread(&id, 4, 1, fd) != 1 ) goto error; } // Skip over chunk size, offset, and blocksize fields if ( fseek(fd, 12, SEEK_CUR) == -1 ) goto error; dataOffset = ftell(fd); byteswap = false; if( little_endian ) byteswap = true; return true; error: sprintf(msg, "[chuck](via WvIn): Error reading AIFF file (%s).", fileName); return false; } bool WvIn :: getMatInfo( const char *fileName ) { // Verify this is a version 5 MAT-file format. char head[4]; if ( fseek(fd, 0, SEEK_SET) == -1 ) goto error; if ( fread(&head, 4, 1, fd) != 1 ) goto error; // If any of the first 4 characters of the header = 0, then this is // a Version 4 MAT-file. if ( strstr(head, "0") ) { sprintf(msg, "[chuck](via WvIn): %s appears to be a Version 4 MAT-file, which is not currently supported.", fileName); return false; } // Determine the endian-ness of the file. char mi[2]; byteswap = false; // Locate "M" and "I" characters in header. if ( fseek(fd, 126, SEEK_SET) == -1 ) goto error; if ( fread(&mi, 2, 1, fd) != 1) goto error; if( little_endian ) { if ( !strncmp(mi, "MI", 2) ) byteswap = true; else if ( strncmp(mi, "IM", 2) ) goto error; } else { if ( !strncmp(mi, "IM", 2)) byteswap = true; else if ( strncmp(mi, "MI", 2) ) goto error; } // Check the data element type SINT32 datatype; if ( fread(&datatype, 4, 1, fd) != 1 ) goto error; if ( byteswap ) swap32((unsigned char *)&datatype); if (datatype != 14) { sprintf(msg, "[chuck](via WvIn): The file does not contain a single Matlab array (or matrix) data element."); return false; } // Determine the array data type. SINT32 tmp; SINT32 size; if ( fseek(fd, 168, SEEK_SET) == -1 ) goto error; if ( fread(&tmp, 4, 1, fd) != 1 ) goto error; if (byteswap) swap32((unsigned char *)&tmp); if (tmp == 1) { // array name > 4 characters if ( fread(&tmp, 4, 1, fd) != 1 ) goto error; // get array name length if (byteswap) swap32((unsigned char *)&tmp); size = (SINT32) ceil((float)tmp / 8); if ( fseek(fd, size*8, SEEK_CUR) == -1 ) goto error; // jump over array name } else { // array name <= 4 characters, compressed data element if ( fseek(fd, 4, SEEK_CUR) == -1 ) goto error; } if ( fread(&tmp, 4, 1, fd) != 1 ) goto error; if (byteswap) swap32((unsigned char *)&tmp); if ( tmp == 1 ) dataType = STK_SINT8; else if ( tmp == 3 ) dataType = STK_SINT16; else if ( tmp == 5 ) dataType = STK_SINT32; else if ( tmp == 7 ) dataType = MY_FLOAT32; else if ( tmp == 9 ) dataType = MY_FLOAT64; else { sprintf(msg, "[chuck](via WvIn): The MAT-file array data format (%d) is not supported.", tmp); return false; } // Get number of rows from the header. SINT32 rows; if ( fseek(fd, 160, SEEK_SET) == -1 ) goto error; if ( fread(&rows, 4, 1, fd) != 1 ) goto error; if (byteswap) swap32((unsigned char *)&rows); // Get number of columns from the header. SINT32 columns; if ( fread(&columns,4, 1, fd) != 1 ) goto error; if (byteswap) swap32((unsigned char *)&columns); // Assume channels = smaller of rows or columns. if (rows < columns) { channels = rows; fileSize = columns; } else { sprintf(msg, "[chuck](via WvIn): Transpose the MAT-file array so that audio channels fill matrix rows (not columns)."); return false; } bufferSize = fileSize; if (fileSize > CHUNK_THRESHOLD) { chunking = true; bufferSize = CHUNK_SIZE; } // Move read pointer to the data in the file. SINT32 headsize; if ( fseek(fd, 132, SEEK_SET) == -1 ) goto error; if ( fread(&headsize, 4, 1, fd) != 1 ) goto error; // file size from 132nd byte if (byteswap) swap32((unsigned char *)&headsize); headsize -= fileSize * 8 * channels; if ( fseek(fd, headsize, SEEK_CUR) == -1 ) goto error; dataOffset = ftell(fd); // Assume MAT-files have 44100 Hz sample rate. fileRate = 44100.0; // Set default rate based on file sampling rate. rate = (MY_FLOAT) ( fileRate / sampleRate() ); return true; error: sprintf(msg, "[chuck](via WvIn): Error reading MAT-file (%s).", fileName); return false; } void WvIn :: readData( unsigned long index ) { while (index < (unsigned long)chunkPointer) { // Negative rate. chunkPointer -= CHUNK_SIZE; bufferSize = CHUNK_SIZE; if (chunkPointer < 0) { bufferSize += chunkPointer; chunkPointer = 0; } } while (index >= chunkPointer+bufferSize) { // Positive rate. chunkPointer += CHUNK_SIZE; bufferSize = CHUNK_SIZE; if ( (unsigned long)chunkPointer+CHUNK_SIZE >= fileSize) { bufferSize = fileSize - chunkPointer; } } long i, length = bufferSize; bool endfile = (chunkPointer+bufferSize == fileSize); if ( !endfile ) length += 1; // Read samples into data[]. Use MY_FLOAT data structure // to store samples. if ( dataType == STK_SINT16 ) { SINT16 *buf = (SINT16 *)data; if (fseek(fd, dataOffset+(long)(chunkPointer*channels*2), SEEK_SET) == -1) goto error; if (fread(buf, length*channels, 2, fd) != 2 ) goto error; if ( byteswap ) { SINT16 *ptr = buf; for (i=length*channels-1; i>=0; i--) swap16((unsigned char *)(ptr++)); } for (i=length*channels-1; i>=0; i--) data[i] = buf[i]; } else if ( dataType == STK_SINT32 ) { SINT32 *buf = (SINT32 *)data; if (fseek(fd, dataOffset+(long)(chunkPointer*channels*4), SEEK_SET) == -1) goto error; if (fread(buf, length*channels, 4, fd) != 4 ) goto error; if ( byteswap ) { SINT32 *ptr = buf; for (i=length*channels-1; i>=0; i--) swap32((unsigned char *)(ptr++)); } for (i=length*channels-1; i>=0; i--) data[i] = buf[i]; } else if ( dataType == MY_FLOAT32 ) { FLOAT32 *buf = (FLOAT32 *)data; if (fseek(fd, dataOffset+(long)(chunkPointer*channels*4), SEEK_SET) == -1) goto error; if (fread(buf, length*channels, 4, fd) != 4 ) goto error; if ( byteswap ) { FLOAT32 *ptr = buf; for (i=length*channels-1; i>=0; i--) swap32((unsigned char *)(ptr++)); } for (i=length*channels-1; i>=0; i--) data[i] = buf[i]; } else if ( dataType == MY_FLOAT64 ) { FLOAT64 *buf = (FLOAT64 *)data; if (fseek(fd, dataOffset+(long)(chunkPointer*channels*8), SEEK_SET) == -1) goto error; if (fread(buf, length*channels, 8, fd) != 8 ) goto error; if ( byteswap ) { FLOAT64 *ptr = buf; for (i=length*channels-1; i>=0; i--) swap64((unsigned char *)(ptr++)); } for (i=length*channels-1; i>=0; i--) data[i] = buf[i]; } else if ( dataType == STK_SINT8 ) { unsigned char *buf = (unsigned char *)data; if (fseek(fd, dataOffset+(long)(chunkPointer*channels), SEEK_SET) == -1) goto error; if (fread(buf, length*channels, 1, fd) != 1 ) goto error; for (i=length*channels-1; i>=0; i--) data[i] = buf[i] - 128.0; // 8-bit WAV data is unsigned! } // If at end of file, repeat last sample frame for interpolation. if ( endfile ) { for (unsigned int j=0; jnormalize((MY_FLOAT) 1.0); } // Normalize all channels equally by the greatest magnitude in all of the data. void WvIn :: normalize(MY_FLOAT peak) { if (chunking) { if ( dataType == STK_SINT8 ) gain = peak / 128.0; else if ( dataType == STK_SINT16 ) gain = peak / 32768.0; else if ( dataType == STK_SINT32 ) gain = peak / 2147483648.0; else if ( dataType == MY_FLOAT32 || dataType == MY_FLOAT64 ) gain = peak; return; } unsigned long i; MY_FLOAT max = (MY_FLOAT) 0.0; for (i=0; i max) max = (MY_FLOAT) fabs((double) data[i]); } if (max > 0.0) { max = (MY_FLOAT) 1.0 / max; max *= peak; for (i=0;i<=channels*bufferSize;i++) data[i] *= max; } } unsigned long WvIn :: getSize(void) const { return fileSize; } unsigned int WvIn :: getChannels(void) const { return channels; } MY_FLOAT WvIn :: getFileRate(void) const { return fileRate; } bool WvIn :: isFinished(void) const { return finished; } void WvIn :: setRate(MY_FLOAT aRate) { rate = aRate; // If negative rate and at beginning of sound, move pointer to end // of sound. if ( (rate < 0) && (time == 0.0) ) time += rate + fileSize; if (fmod(rate, 1.0) != 0.0) interpolate = true; else interpolate = false; } void WvIn :: addTime(MY_FLOAT aTime) { // Add an absolute time in samples time += aTime; if (time < 0.0) time = 0.0; if (time >= fileSize) { time = fileSize; finished = true; } } void WvIn :: setInterpolate(bool doInterpolate) { interpolate = doInterpolate; } const MY_FLOAT *WvIn :: lastFrame(void) const { return lastOutput; } MY_FLOAT WvIn :: lastOut(void) const { if ( channels == 1 ) return *lastOutput; MY_FLOAT output = 0.0; for (unsigned int i=0; i= chunkPointer+bufferSize) ) this->readData((long) tyme); // Adjust index for the current buffer. tyme -= chunkPointer; } // Integer part of time address. index = (long) tyme; if (interpolate) { // Linear interpolation ... fractional part of time address. alpha = tyme - (MY_FLOAT) index; index *= channels; for (i=0; i= fileSize ) finished = true; return lastOutput; } MY_FLOAT *WvIn :: tickFrame(MY_FLOAT *frameVector, unsigned int frames) { unsigned int j; for ( unsigned int i=0; i 255 ) // m_filename[255] = '\0'; if ( nChannels < 1 ) { sprintf(msg, "[chuck](via WvOut): the channels argument must be greater than zero!"); handleError( msg, StkError::FUNCTION_ARGUMENT ); } unsigned int lastChannels = channels; channels = nChannels; fileType = type; if ( format != STK_SINT8 && format != STK_SINT16 && format != STK_SINT32 && format != MY_FLOAT32 && format != MY_FLOAT64 ) { sprintf( msg, "[chuck](via WvOut): Unknown data type specified (%ld).", format ); handleError(msg, StkError::FUNCTION_ARGUMENT); } dataType = format; bool result = false; if ( fileType == WVOUT_RAW ) { if ( channels != 1 ) { sprintf(msg, "[chuck](via WvOut): STK RAW files are, by definition, always monaural (channels = %d not supported)!", nChannels); handleError( msg, StkError::FUNCTION_ARGUMENT ); } result = setRawFile( fileName ); } else if ( fileType == WVOUT_WAV ) result = setWavFile( fileName ); else if ( fileType == WVOUT_SND ) result = setSndFile( fileName ); else if ( fileType == WVOUT_AIF ) result = setAifFile( fileName ); else if ( fileType == WVOUT_MAT ) result = setMatFile( fileName ); else { sprintf(msg, "[chuck](via WvOut): Unknown file type specified (%ld).", fileType); handleError(msg, StkError::FUNCTION_ARGUMENT); } if ( result == false ) handleError(msg, StkError::FILE_ERROR); // Allocate new memory if necessary. if ( lastChannels < channels ) { if ( data ) delete [] data; data = (MY_FLOAT *) new MY_FLOAT[BUFFER_SIZE*channels]; } counter = 0; } bool WvOut :: setRawFile( const char *fileName ) { char name[128]; strncpy(name, fileName, 128); if ( strstr(name, ".raw") == NULL) strcat(name, ".raw"); fd = fopen(name, "wb"); if ( !fd ) { sprintf(msg, "[chuck](via WvOut): Could not create RAW file: %s", name); return false; } if ( dataType != STK_SINT16 ) { dataType = STK_SINT16; sprintf(msg, "[chuck](via WvOut): Using 16-bit signed integer data format for file %s.", name); handleError(msg, StkError::WARNING); } byteswap = false; if( little_endian ) byteswap = true; // printf("\nCreating RAW file: %s\n", name); return true; } bool WvOut :: setWavFile( const char *fileName ) { char name[128]; strncpy(name, fileName, 128); if ( strstr(name, ".wav") == NULL) strcat(name, ".wav"); fd = fopen(name, "wb"); if ( !fd ) { sprintf(msg, "[chuck](via WvOut): Could not create WAV file: %s", name); return false; } struct wavhdr hdr = {"RIF", 44, "WAV", "fmt", 16, 1, 1, (SINT32) Stk::sampleRate(), 0, 2, 16, "dat", 0}; hdr.riff[3] = 'F'; hdr.wave[3] = 'E'; hdr.fmt[3] = ' '; hdr.data[3] = 'a'; hdr.num_chans = (SINT16) channels; if ( dataType == STK_SINT8 ) hdr.bits_per_samp = 8; else if ( dataType == STK_SINT16 ) hdr.bits_per_samp = 16; else if ( dataType == STK_SINT32 ) hdr.bits_per_samp = 32; else if ( dataType == MY_FLOAT32 ) { hdr.format_tag = 3; hdr.bits_per_samp = 32; } else if ( dataType == MY_FLOAT64 ) { hdr.format_tag = 3; hdr.bits_per_samp = 64; } hdr.bytes_per_samp = (SINT16) (channels * hdr.bits_per_samp / 8); hdr.bytes_per_sec = (SINT32) (hdr.sample_rate * hdr.bytes_per_samp); byteswap = false; if( !little_endian ) { byteswap = true; swap32((unsigned char *)&hdr.file_size); swap32((unsigned char *)&hdr.chunk_size); swap16((unsigned char *)&hdr.format_tag); swap16((unsigned char *)&hdr.num_chans); swap32((unsigned char *)&hdr.sample_rate); swap32((unsigned char *)&hdr.bytes_per_sec); swap16((unsigned char *)&hdr.bytes_per_samp); swap16((unsigned char *)&hdr.bits_per_samp); } if ( fwrite(&hdr, 4, 11, fd) != 11 ) { sprintf(msg, "[chuck](via WvOut): Could not write WAV header for file %s", name); return false; } // printf("\nCreating WAV file: %s\n", name); return true; } void WvOut :: closeWavFile( void ) { int bytes_per_sample = 1; if ( dataType == STK_SINT16 ) bytes_per_sample = 2; else if ( dataType == STK_SINT32 || dataType == MY_FLOAT32 ) bytes_per_sample = 4; else if ( dataType == MY_FLOAT64 ) bytes_per_sample = 8; SINT32 bytes = totalCount * channels * bytes_per_sample; if( !little_endian ) swap32((unsigned char *)&bytes); fseek(fd, 40, SEEK_SET); // jump to data length fwrite(&bytes, 4, 1, fd); bytes = totalCount * channels * bytes_per_sample + 44; if( !little_endian ) swap32((unsigned char *)&bytes); fseek(fd, 4, SEEK_SET); // jump to file size fwrite(&bytes, 4, 1, fd); fclose( fd ); } bool WvOut :: setSndFile( const char *fileName ) { char name[128]; strncpy(name, fileName, 128); if ( strstr(name, ".snd") == NULL) strcat(name, ".snd"); fd = fopen(name, "wb"); if ( !fd ) { sprintf(msg, "[chuck](via WvOut): Could not create SND file: %s", name); return false; } struct sndhdr hdr = {".sn", 40, 0, 3, (SINT32) Stk::sampleRate(), 1, "Created by STK"}; hdr.pref[3] = 'd'; hdr.num_channels = channels; if ( dataType == STK_SINT8 ) hdr.format = 2; else if ( dataType == STK_SINT16 ) hdr.format = 3; else if ( dataType == STK_SINT32 ) hdr.format = 5; else if ( dataType == MY_FLOAT32 ) hdr.format = 6; else if ( dataType == MY_FLOAT64 ) hdr.format = 7; byteswap = false; if( little_endian ) { byteswap = true; swap32 ((unsigned char *)&hdr.hdr_length); swap32 ((unsigned char *)&hdr.format); swap32 ((unsigned char *)&hdr.sample_rate); swap32 ((unsigned char *)&hdr.num_channels); } if ( fwrite(&hdr, 4, 10, fd) != 10 ) { sprintf(msg, "[chuck](via WvOut): Could not write SND header for file %s", name); return false; } // printf("\nCreating SND file: %s\n", name); return true; } void WvOut :: closeSndFile( void ) { int bytes_per_sample = 1; if ( dataType == STK_SINT16 ) bytes_per_sample = 2; else if ( dataType == STK_SINT32 ) bytes_per_sample = 4; else if ( dataType == MY_FLOAT32 ) bytes_per_sample = 4; else if ( dataType == MY_FLOAT64 ) bytes_per_sample = 8; SINT32 bytes = totalCount * bytes_per_sample * channels; if( little_endian ) swap32 ((unsigned char *)&bytes); fseek(fd, 8, SEEK_SET); // jump to data size fwrite(&bytes, 4, 1, fd); fclose(fd); } bool WvOut :: setAifFile( const char *fileName ) { char name[128]; strncpy(name, fileName, 128); if ( strstr(name, ".aif") == NULL) strcat(name, ".aif"); fd = fopen(name, "wb"); if ( !fd ) { sprintf(msg, "[chuck](via WvOut): Could not create AIF file: %s", name); return false; } // Common parts of AIFF/AIFC header. struct aifhdr hdr = {"FOR", 46, "AIF", "COM", 18, 0, 0, 16, "0"}; struct aifssnd ssnd = {"SSN", 8, 0, 0}; hdr.form[3] = 'M'; hdr.aiff[3] = 'F'; hdr.comm[3] = 'M'; ssnd.ssnd[3] = 'D'; hdr.num_chans = channels; if ( dataType == STK_SINT8 ) hdr.sample_size = 8; else if ( dataType == STK_SINT16 ) hdr.sample_size = 16; else if ( dataType == STK_SINT32 ) hdr.sample_size = 32; else if ( dataType == MY_FLOAT32 ) { hdr.aiff[3] = 'C'; hdr.sample_size = 32; hdr.comm_size = 24; } else if ( dataType == MY_FLOAT64 ) { hdr.aiff[3] = 'C'; hdr.sample_size = 64; hdr.comm_size = 24; } // For AIFF files, the sample rate is stored in a 10-byte, // IEEE Standard 754 floating point number, so we need to // convert to that. SINT16 i; unsigned long exp; unsigned long rate = (unsigned long) Stk::sampleRate(); memset(hdr.srate, 0, 10); exp = rate; for (i=0; i<32; i++) { exp >>= 1; if (!exp) break; } i += 16383; if( little_endian ) swap16((unsigned char *)&i); *(SINT16 *)(hdr.srate) = (SINT16) i; for (i=32; i; i--) { if (rate & 0x80000000) break; rate <<= 1; } if( little_endian ) swap32((unsigned char *)&rate); *(unsigned long *)(hdr.srate+2) = (unsigned long) rate; byteswap = false; if( little_endian ) { byteswap = true; swap32((unsigned char *)&hdr.form_size); swap32((unsigned char *)&hdr.comm_size); swap16((unsigned char *)&hdr.num_chans); swap16((unsigned char *)&hdr.sample_size); swap32((unsigned char *)&ssnd.ssnd_size); swap32((unsigned char *)&ssnd.offset); swap32((unsigned char *)&ssnd.block_size); } // The structure boundaries don't allow a single write of 54 bytes. if ( fwrite(&hdr, 4, 5, fd) != 5 ) goto error; if ( fwrite(&hdr.num_chans, 2, 1, fd) != 1 ) goto error; if ( fwrite(&hdr.sample_frames, 4, 1, fd) != 1 ) goto error; if ( fwrite(&hdr.sample_size, 2, 1, fd) != 1 ) goto error; if ( fwrite(&hdr.srate, 10, 1, fd) != 1 ) goto error; if ( dataType == MY_FLOAT32 ) { char type[4] = {'f','l','3','2'}; char zeroes[2] = { 0, 0 }; if ( fwrite(&type, 4, 1, fd) != 1 ) goto error; if ( fwrite(&zeroes, 2, 1, fd) != 1 ) goto error; } else if ( dataType == MY_FLOAT64 ) { char type[4] = {'f','l','6','4'}; char zeroes[2] = { 0, 0 }; if ( fwrite(&type, 4, 1, fd) != 1 ) goto error; if ( fwrite(&zeroes, 2, 1, fd) != 1 ) goto error; } if ( fwrite(&ssnd, 4, 4, fd) != 4 ) goto error; // printf("\nCreating AIF file: %s\n", name); return true; error: sprintf(msg, "[chuck](via WvOut): Could not write AIF header for file %s", name); return false; } void WvOut :: closeAifFile( void ) { unsigned long frames = (unsigned long) totalCount; if( little_endian ) swap32((unsigned char *)&frames); fseek(fd, 22, SEEK_SET); // jump to "COMM" sample_frames fwrite(&frames, 4, 1, fd); int bytes_per_sample = 1; if ( dataType == STK_SINT16 ) bytes_per_sample = 2; else if ( dataType == STK_SINT32 || dataType == MY_FLOAT32 ) bytes_per_sample = 4; else if ( dataType == MY_FLOAT64 ) bytes_per_sample = 8; unsigned long bytes = totalCount * bytes_per_sample * channels + 46; if ( dataType == MY_FLOAT32 || dataType == MY_FLOAT64 ) bytes += 6; if( little_endian ) swap32((unsigned char *)&bytes); fseek(fd, 4, SEEK_SET); // jump to file size fwrite(&bytes, 4, 1, fd); bytes = totalCount * bytes_per_sample * channels + 8; if ( dataType == MY_FLOAT32 || dataType == MY_FLOAT64 ) bytes += 6; if( little_endian ) swap32((unsigned char *)&bytes); if ( dataType == MY_FLOAT32 || dataType == MY_FLOAT64 ) fseek(fd, 48, SEEK_SET); // jump to "SSND" chunk size else fseek(fd, 42, SEEK_SET); // jump to "SSND" chunk size fwrite(&bytes, 4, 1, fd); fclose( fd ); } bool WvOut :: setMatFile( const char *fileName ) { char name[128]; strncpy(name, fileName, 128); if ( strstr(name, ".mat") == NULL) strcat(name, ".mat"); fd = fopen(name, "w+b"); if ( !fd ) { sprintf(msg, "[chuck](via WvOut): Could not create MAT file: %s", name); return false; } if ( dataType != MY_FLOAT64 ) { dataType = MY_FLOAT64; sprintf(msg, "[chuck](via WvOut): Using 64-bit floating-point data format for file %s", name); handleError(msg, StkError::WARNING); } struct mathdr hdr; strcpy(hdr.heading,"MATLAB 5.0 MAT-file, Generated using the Synthesis ToolKit in C++ (STK). By Perry R. Cook and Gary P. Scavone, 1995-2002."); int i; for (i=strlen(hdr.heading);i<124;i++) hdr.heading[i] = ' '; // Header Flag Fields hdr.hff[0] = (SINT16) 0x0100; // Version field hdr.hff[1] = (SINT16) 'M'; // Endian indicator field ("MI") hdr.hff[1] <<= 8; hdr.hff[1] += 'I'; hdr.adf[0] = (SINT32) 14; // Matlab array data type value hdr.adf[1] = (SINT32) 0; // Size of file after this point to end (in bytes) // Don't know size yet. // Numeric Array Subelements (4): // 1. Array Flags hdr.adf[2] = (SINT32) 6; // Matlab 32-bit unsigned integer data type value hdr.adf[3] = (SINT32) 8; // 8 bytes of data to follow hdr.adf[4] = (SINT32) 6; // Double-precision array, no array flags set hdr.adf[5] = (SINT32) 0; // 4 bytes undefined // 2. Array Dimensions hdr.adf[6] = (SINT32) 5; // Matlab 32-bit signed integer data type value hdr.adf[7] = (SINT32) 8; // 8 bytes of data to follow (2D array) hdr.adf[8] = (SINT32) channels; // This is the number of rows hdr.adf[9] = (SINT32) 0; // This is the number of columns // 3. Array Name // We'll use fileName for the matlab array name (as well as the file name). // If fileName is 4 characters or less, we have to use a compressed data element // format for the array name data element. Otherwise, the array name must // be formatted in 8-byte increments (up to 31 characters + NULL). SINT32 namelength = (SINT32) strlen(fileName); if (strstr(fileName, ".mat")) namelength -= 4; if (namelength > 31) namelength = 31; // Truncate name to 31 characters. char arrayName[64]; strncpy(arrayName, fileName, namelength); arrayName[namelength] = '\0'; if (namelength > 4) { hdr.adf[10] = (SINT32) 1; // Matlab 8-bit signed integer data type value } else { // Compressed data element format hdr.adf[10] = namelength; hdr.adf[10] <<= 16; hdr.adf[10] += 1; } SINT32 headsize = 40; // Number of bytes in data element so far. // Write the fixed portion of the header if ( fwrite(&hdr, 172, 1, fd) != 1 ) goto error; // Write MATLAB array name SINT32 tmp; if (namelength > 4) { if ( fwrite(&namelength, 4, 1, fd) != 1) goto error; if ( fwrite(arrayName, namelength, 1, fd) != 1 ) goto error; tmp = (SINT32) ceil((float)namelength / 8); if ( fseek(fd, tmp*8-namelength, SEEK_CUR) == -1 ) goto error; headsize += tmp * 8; } else { // Compressed data element format if ( fwrite(arrayName, namelength, 1, fd) != 1 ) goto error; tmp = 4 - namelength; if ( fseek(fd, tmp, SEEK_CUR) == -1 ) goto error; } // Finish writing known header information tmp = 9; // Matlab IEEE 754 double data type if ( fwrite(&tmp, 4, 1, fd) != 1 ) goto error; tmp = 0; // Size of real part subelement in bytes (8 per sample) if ( fwrite(&tmp, 4, 1, fd) != 1 ) goto error; headsize += 8; // Total number of bytes in data element so far if ( fseek(fd, 132, SEEK_SET) == -1 ) goto error; if ( fwrite(&headsize, 4, 1, fd) != 1 ) goto error; // Write header size ... will update at end if ( fseek(fd, 0, SEEK_END) == -1 ) goto error; byteswap = false; fprintf( stderr, "[chuck]:(via STK): creating MAT-file (%s) containing MATLAB array: %s\n", name, arrayName); return true; error: sprintf(msg, "[chuck](via WvOut): Could not write MAT-file header for file %s", name); return false; } void WvOut :: closeMatFile( void ) { fseek(fd, 164, SEEK_SET); // jump to number of columns fwrite(&totalCount, 4, 1, fd); SINT32 headsize, temp; fseek(fd, 132, SEEK_SET); // jump to header size fread(&headsize, 4, 1, fd); temp = headsize; headsize += (SINT32) (totalCount * 8 * channels); fseek(fd, 132, SEEK_SET); // Write file size (minus some header info) fwrite(&headsize, 4, 1, fd); fseek(fd, temp+132, SEEK_SET); // jumpt to data size (in bytes) temp = totalCount * 8 * channels; fwrite(&temp, 4, 1, fd); fclose(fd); } unsigned long WvOut :: getFrames( void ) const { return totalCount; } MY_FLOAT WvOut :: getTime( void ) const { return (MY_FLOAT) totalCount / Stk::sampleRate(); } void WvOut :: writeData( unsigned long frames ) { if ( dataType == STK_SINT8 ) { if ( fileType == WVOUT_WAV ) { // 8-bit WAV data is unsigned! unsigned char sample; for ( unsigned long k=0; k= 8192 ) { flush = 0; fflush( fd ); } return; error: sprintf(msg, "[chuck](via WvOut): Error writing data to file."); handleError(msg, StkError::FILE_ERROR); } void WvOut :: tick(const MY_FLOAT sample) { if ( !fd ) return; for ( unsigned int j=0; j>16)&&0xff; unsigned char data1 = (i>>8)&&0xff; unsigned char data2 = (i)&&0xff; } void ck_domidi ( Instrmnt * inst, unsigned char status, unsigned char data1, unsigned char data2) { unsigned char type = status && 0xf0; switch ( type ) { case __SK_NoteOn_: inst->noteOn( mtof ( (float)data1 ), ((float)data2) / 128.0 ); break; case __SK_NoteOff_: inst->noteOff( ((float)data2) / 128.0 ); break; case __SK_ControlChange_: inst->controlChange( data1, data2 ); break; case __SK_AfterTouch_: inst->controlChange( __SK_AfterTouch_, ((float)data1) / 128.0 ); case __SK_PitchBend_: unsigned int mnum = ((unsigned int)data2) << 7 || data1 ); inst->controlChange( __SK_PitchBend_, ((float)mnum) / 16384.0 ); break; } } */ // StkInstrument //----------------------------------------------------------------------------- // name: Instrmnt_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Instrmnt_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)0; // fprintf( stderr,"[chuck](via STK): error : StkInstrument is virtual!\n"); } //----------------------------------------------------------------------------- // name: Instrmnt_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Instrmnt_dtor ) { // should be done already by now } //----------------------------------------------------------------------------- // name: Instrmnt_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Instrmnt_tick ) { Instrmnt * i = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); if( !out ) fprintf( stderr,"[chuck](via STK): we warned you...\n"); *out = i->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: BlowBotl_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Instrmnt_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Instrmnt_ctrl_noteOn() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Instrmnt_ctrl_noteOn ) { Instrmnt * i = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); i->noteOn( i->m_frequency, f ); } //----------------------------------------------------------------------------- // name: Instrmnt_ctrl_noteOff() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Instrmnt_ctrl_noteOff ) { Instrmnt * i = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); i->noteOff( f ); } //----------------------------------------------------------------------------- // name: Instrmnt_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Instrmnt_ctrl_freq ) { Instrmnt * i = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); i->setFrequency( f ); RETURN->v_float = (t_CKFLOAT)i->m_frequency; } //----------------------------------------------------------------------------- // name: Instrmnt_cget_freq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Instrmnt_cget_freq ) { Instrmnt * i = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); RETURN->v_float = (t_CKFLOAT)i->m_frequency; } //----------------------------------------------------------------------------- // name: Instrmnt_ctrl_controlChange() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL(Instrmnt_ctrl_controlChange ) { Instrmnt * ii = (Instrmnt *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKINT i = GET_NEXT_INT(ARGS); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); ii->controlChange( i, f ); } //----------------------------------------------------------------------------- // name: BandedWG_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BandedWG_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new BandedWG(); } //----------------------------------------------------------------------------- // name: BandedWG_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( BandedWG_dtor ) { delete (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: BandedWG_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BandedWG_tick ) { *out = ((BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data))->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: BandedWG_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BandedWG_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_pluck() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_pluck ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->pluck( GET_NEXT_FLOAT(ARGS)); } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_strikePosition() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_strikePosition ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->setStrikePosition( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)f->m_strikePosition; } //----------------------------------------------------------------------------- // name: BandedWG_cget_strikePosition() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_strikePosition ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)f->m_strikePosition; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_bowRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_bowRate ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->m_rate = GET_NEXT_FLOAT(ARGS); RETURN->v_float = (t_CKFLOAT) f->m_rate; } //----------------------------------------------------------------------------- // name: BandedWG_cget_bowRate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_bowRate ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) f->m_rate; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_bowPressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_bowPressure ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->controlChange( __SK_BowPressure_, GET_NEXT_FLOAT(ARGS) * 128.0 ); RETURN->v_float = (t_CKFLOAT)f->m_bowPressure; } //----------------------------------------------------------------------------- // name: BandedWG_cget_bowPressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_bowPressure ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)f->m_bowPressure; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_bowMotion() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_bowMotion ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->controlChange( 4, GET_NEXT_FLOAT(ARGS) * 128.0 ); RETURN->v_float = (t_CKFLOAT)f->m_bowMotion; } //----------------------------------------------------------------------------- // name: BandedWG_cget_bowMotion() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_bowMotion ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)f->m_bowMotion; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_vibratoFreq ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->controlChange( 4, GET_NEXT_FLOAT(ARGS) * 128.0 ); RETURN->v_float = (t_CKFLOAT)f->integrationConstant; } //----------------------------------------------------------------------------- // name: BandedWG_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_vibratoFreq ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)f->integrationConstant; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_modesGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_modesGain ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->controlChange( 1, GET_NEXT_FLOAT(ARGS) * 128.0 ); RETURN->v_float = (t_CKFLOAT)f->m_modesGain; } //----------------------------------------------------------------------------- // name: BandedWG_cget_modesGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_modesGain ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)f->m_modesGain; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_preset() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_preset ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->setPreset ( GET_NEXT_INT(ARGS) ); RETURN->v_int = (t_CKINT) f->m_preset; } //----------------------------------------------------------------------------- // name: BandedWG_cget_preset() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BandedWG_cget_preset ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_int = (t_CKINT) f->m_preset; } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_startBowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_startBowing ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->startBowing( GET_NEXT_FLOAT(ARGS), f->m_rate ); } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_stopBowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_stopBowing ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); f->stopBowing( GET_NEXT_FLOAT(ARGS) ); } //----------------------------------------------------------------------------- // name: BandedWG_ctrl_controlChange() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BandedWG_ctrl_controlChange ) { BandedWG * f = (BandedWG *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKINT i = GET_NEXT_INT(ARGS); t_CKFLOAT v = GET_NEXT_FLOAT(ARGS); f->controlChange( i, v ); } // BiQuad struct BiQuad_ { BiQuad biquad; t_CKFLOAT pfreq; t_CKFLOAT prad; t_CKFLOAT zfreq; t_CKFLOAT zrad; t_CKBOOL norm; }; //----------------------------------------------------------------------------- // name: BiQuad_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BiQuad_ctor ) { BiQuad_ * d = new BiQuad_; d->pfreq = 0.0; d->prad = 0.0; d->zfreq = 0.0; d->zrad = 0.0; d->norm = FALSE; OBJ_MEMBER_UINT(SELF, BiQuad_offset_data) = (t_CKUINT)d; } //----------------------------------------------------------------------------- // name: BiQuad_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( BiQuad_dtor ) { delete (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); OBJ_MEMBER_UINT(SELF, BiQuad_offset_data) = 0; } //----------------------------------------------------------------------------- // name: BiQuad_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BiQuad_tick ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); *out = (SAMPLE)f->biquad.tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: BiQuad_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BiQuad_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_b2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_b2 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setB2( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT) f->biquad.b[2]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_b2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_b2 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.b[2]; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_b1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_b1 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setB1( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT) f->biquad.b[1]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_b1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_b1 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.b[1]; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_b0 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setB0( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT) f->biquad.b[0]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_b0 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.b[0]; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_a2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_a2 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setA2( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT) f->biquad.a[2]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_a2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_a2 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.a[2]; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_a1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_a1 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setA1( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT) f->biquad.a[1]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_a1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_a1 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.a[1]; } //----------------------------------------------------------------------------- // name: BiQuad_cget_a0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BiQuad_cget_a0 ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT) f->biquad.a[0]; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_pfreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_pfreq ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->pfreq = GET_NEXT_FLOAT(ARGS); f->biquad.setResonance( f->pfreq, f->prad, f->norm != 0 ); RETURN->v_float = (t_CKFLOAT)f->pfreq; } //----------------------------------------------------------------------------- // name: BiQuad_cget_pfreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_cget_pfreq ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT)f->pfreq; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_prad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_prad ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->prad = GET_NEXT_FLOAT(ARGS); f->biquad.setResonance( f->pfreq, f->prad, f->norm != 0 ); RETURN->v_float = (t_CKFLOAT)f->prad; } //----------------------------------------------------------------------------- // name: BiQuad_cget_prad() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_cget_prad ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT)f->prad; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_zfreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_zfreq ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->zfreq = GET_NEXT_FLOAT(ARGS); f->biquad.setNotch( f->zfreq, f->zrad ); RETURN->v_float = (t_CKFLOAT)f->zfreq; } //----------------------------------------------------------------------------- // name: BiQuad_cget_zfreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_cget_zfreq ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = (t_CKFLOAT)f->zfreq; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_zrad() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_zrad ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->zrad = GET_NEXT_FLOAT(ARGS); f->biquad.setNotch( f->zfreq, f->zrad ); RETURN->v_float = f->zrad; } //----------------------------------------------------------------------------- // name: BiQuad_cget_zrad() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_cget_zrad ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); RETURN->v_float = f->zrad; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_norm() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_norm ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->norm = GET_NEXT_UINT(ARGS) != 0; f->biquad.setResonance( f->pfreq, f->prad, f->norm != 0 ); RETURN->v_int = f->norm; } //----------------------------------------------------------------------------- // name: BiQuad_ctrl_eqzs() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BiQuad_ctrl_eqzs ) { BiQuad_ * f = (BiQuad_ *)OBJ_MEMBER_UINT(SELF, BiQuad_offset_data); f->biquad.setEqualGainZeroes(); } // BlowBotl //----------------------------------------------------------------------------- // name: BlowBotl_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BlowBotl_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new BlowBotl(); } //----------------------------------------------------------------------------- // name: BlowBotl_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( BlowBotl_dtor ) { delete (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: BlowBotl_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BlowBotl_tick ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = p->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: BlowBotl_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BlowBotl_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_startBlowing ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->startBlowing( f ); } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_stopBlowing ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_rate ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->m_rate = f; RETURN->v_float = (t_CKFLOAT)p->m_rate; } //----------------------------------------------------------------------------- // name: BlowBotl_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowBotl_cget_rate ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) p->m_rate; } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_noiseGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_noiseGain ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 4, f * 128 ); RETURN->v_float = (t_CKFLOAT)p->m_noiseGain; } //----------------------------------------------------------------------------- // name: BlowBotl_cget_noiseGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowBotl_cget_noiseGain ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_noiseGain; } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_vibratoFreq ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setVibratoFreq( f ); RETURN->v_float = (t_CKFLOAT)p->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: BlowBotl_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowBotl_cget_vibratoFreq ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_vibratoGain ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 1, f * 128 ); RETURN->v_float = (t_CKFLOAT)p->m_vibratoGain; } //----------------------------------------------------------------------------- // name: BlowBotl_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowBotl_cget_vibratoGain ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_vibratoGain; } //----------------------------------------------------------------------------- // name: BlowBotl_ctrl_volume() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowBotl_ctrl_volume ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 128, f * 128 ); RETURN->v_float = (t_CKFLOAT)p->m_volume; } //----------------------------------------------------------------------------- // name: BlowBotl_cget_volume() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowBotl_cget_volume ) { BlowBotl * p = (BlowBotl *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_volume; } // BlowHole //----------------------------------------------------------------------------- // name: BlowHole_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BlowHole_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new BlowHole( 30 ); } //----------------------------------------------------------------------------- // name: BlowHole_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( BlowHole_dtor ) { delete (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: BlowHole_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BlowHole_tick ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = p->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: BlowHole_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BlowHole_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_startBlowing ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->startBlowing ( f ); } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_stopBlowing ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_rate ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->m_rate = f; RETURN->v_float = (t_CKFLOAT)p->m_rate; } //----------------------------------------------------------------------------- // name: BlowHole_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_rate ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_rate; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_tonehole() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_tonehole ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setTonehole( f ); RETURN->v_float = (t_CKFLOAT)p->m_tonehole; } //----------------------------------------------------------------------------- // name: BlowHole_cget_tonehole() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_tonehole ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_tonehole; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_vent() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_vent ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setVent( f ); RETURN->v_float = (t_CKFLOAT)p->m_vent; } //----------------------------------------------------------------------------- // name: BlowHole_cget_vent() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_vent ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_vent; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_reed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_reed ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange(__SK_ReedStiffness_, f * 128.0); RETURN->v_float = (t_CKFLOAT)p->m_reed; } //----------------------------------------------------------------------------- // name: BlowHole_cget_reed() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_reed ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_reed; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_noiseGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_noiseGain ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 4, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_noiseGain; } //----------------------------------------------------------------------------- // name: BlowHole_cget_noiseGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_noiseGain ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_noiseGain; } //----------------------------------------------------------------------------- // name: BlowHole_ctrl_pressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( BlowHole_ctrl_pressure ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 128, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_pressure; } //----------------------------------------------------------------------------- // name: BlowHole_cget_pressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( BlowHole_cget_pressure ) { BlowHole * p = (BlowHole *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_pressure; } // Bowed //----------------------------------------------------------------------------- // name: Bowed_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Bowed_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new Bowed(40.0); } //----------------------------------------------------------------------------- // name: Bowed_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Bowed_dtor ) { delete (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Bowed_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Bowed_tick ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = p->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Bowed_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Bowed_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_startBowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_startBowing ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->startBowing( f ); } //----------------------------------------------------------------------------- // name: Bowed_ctrl_stopBowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_stopBowing ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->stopBowing( f ); } //----------------------------------------------------------------------------- // name: Bowed_ctrl_bowPressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_bowPressure ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 2, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_bowPressure; } //----------------------------------------------------------------------------- // name: Bowed_cget_bowPressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_bowPressure ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_bowPressure; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_bowPos() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_bowPos ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 4, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_bowPosition; } //----------------------------------------------------------------------------- // name: Bowed_cget_bowPos() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_bowPos ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_bowPosition; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_vibratoFreq ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setVibratoFreq( f ); RETURN->v_float = (t_CKFLOAT)p->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Bowed_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_vibratoFreq ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_vibratoGain ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 1, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Bowed_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_vibratoGain ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_volume() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_volume ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->controlChange( 128, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)p->m_volume; } //----------------------------------------------------------------------------- // name: Bowed_cget_volume() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_volume ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)p->m_volume; } //----------------------------------------------------------------------------- // name: Bowed_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Bowed_ctrl_rate ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->m_rate = f; RETURN->v_float = (t_CKFLOAT) p->m_rate; } //----------------------------------------------------------------------------- // name: Bowed_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Bowed_cget_rate ) { Bowed * p = (Bowed *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) p->m_rate; } // Chorus //----------------------------------------------------------------------------- // name: Chorus_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Chorus_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Chorus_offset_data) = (t_CKUINT) new Chorus( 44100 ); } //----------------------------------------------------------------------------- // name: Chorus_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Chorus_dtor ) { delete (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); OBJ_MEMBER_UINT(SELF, Chorus_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Chorus_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Chorus_tick ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); *out = p->tick(in); return TRUE; } //----------------------------------------------------------------------------- // name: Chorus_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Chorus_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Chorus_ctrl_mix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Chorus_ctrl_mix ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setEffectMix( f ); RETURN->v_float = (t_CKFLOAT) p->effectMix; } //----------------------------------------------------------------------------- // name: Chorus_ctrl_modDepth() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Chorus_ctrl_modDepth ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setModDepth( f ); RETURN->v_float = (t_CKFLOAT) p->modDepth; } //----------------------------------------------------------------------------- // name: Chorus_ctrl_modFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Chorus_ctrl_modFreq ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setModFrequency( f ); RETURN->v_float = (t_CKFLOAT) p->mods[0]->m_freq; } //----------------------------------------------------------------------------- // name: Chorus_cget_mix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Chorus_cget_mix ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); RETURN->v_float = (t_CKFLOAT) p->effectMix; } //----------------------------------------------------------------------------- // name: Chorus_cget_modDepth() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Chorus_cget_modDepth ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); RETURN->v_float = (t_CKFLOAT) p->modDepth; } //----------------------------------------------------------------------------- // name: Chorus_cget_modFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Chorus_cget_modFreq ) { Chorus * p = (Chorus *)OBJ_MEMBER_UINT(SELF, Chorus_offset_data); RETURN->v_float = (t_CKFLOAT) p->mods[0]->m_freq; } // Brass /* struct Brass_ { Brass * imp; t_CKFLOAT m_frequency; t_CKFLOAT m_rate; t_CKFLOAT m_lip; Brass_( t_CKFLOAT d ) { imp = new Brass(d); m_frequency = 100.0; m_rate = 0.5; m_lip = 0.1; } ~Brass_() { SAFE_DELETE( imp ); } }; */ //----------------------------------------------------------------------------- // name: Brass_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Brass_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new Brass( 30.0 ); } //----------------------------------------------------------------------------- // name: Brass_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Brass_dtor ) { delete (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Brass_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Brass_tick ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Brass_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Brass_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Brass_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_startBlowing ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->startBlowing( f, b->m_rate ); } //----------------------------------------------------------------------------- // name: Brass_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_stopBlowing ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: Brass_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_clear ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: Brass_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_rate ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->m_rate = f; RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Brass_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_rate ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Brass_ctrl_lip() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_lip ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 2, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_lip; } //----------------------------------------------------------------------------- // name: Brass_cget_lip() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_lip ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_lip; } //----------------------------------------------------------------------------- // name: Brass_ctrl_slide() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_slide ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 4, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_slide; } //----------------------------------------------------------------------------- // name: Brass_cget_slide() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_slide ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_slide; } //----------------------------------------------------------------------------- // name: Brass_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_vibratoFreq ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setVibratoFreq( f ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Brass_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_vibratoFreq ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Brass_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_vibratoGain ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 1, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Brass_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_vibratoGain) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Brass_ctrl_volume() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Brass_ctrl_volume ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 128, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_volume; } //----------------------------------------------------------------------------- // name: Brass_cget_volume() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Brass_cget_volume ) { Brass * b = (Brass *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_volume; } /* struct Clarinet_ { Clarinet * imp; double m_frequency; double m_rate; double m_reed; Clarinet_ ( double d ) { imp = new Clarinet(d); m_frequency = 100.0; m_rate = 0.5; m_reed = 0.5; } }; */ // Clarinet //----------------------------------------------------------------------------- // name: Clarinet_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Clarinet_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new Clarinet( 30.0 ); } //----------------------------------------------------------------------------- // name: Clarinet_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Clarinet_dtor ) { delete (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Clarinet_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Clarinet_tick ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Clarinet_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Clarinet_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_startBlowing ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->startBlowing( f, b->m_rate ); } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_stopBlowing ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_clear ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_reed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_reed ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 2, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_reed; } //----------------------------------------------------------------------------- // name: Clarinet_cget_reed() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_reed ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_reed; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_rate ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->m_rate = f; RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Clarinet_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_rate ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) b->m_rate; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_noiseGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_noiseGain ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 4, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Clarinet_cget_noiseGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_noiseGain ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_vibratoFreq ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setVibratoFreq( f ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Clarinet_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_vibratoFreq ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_vibratoGain ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 1, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Clarinet_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_vibratoGain ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Clarinet_ctrl_pressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Clarinet_ctrl_pressure ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 128, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_volume; } //----------------------------------------------------------------------------- // name: Clarinet_cget_pressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Clarinet_cget_pressure ) { Clarinet * b = (Clarinet *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_volume; } // Flute struct Flute_ { Flute * imp; double m_frequency; double m_rate; double m_jetDelay; double m_jetReflection; double m_endReflection; Flute_ ( double d ) { imp = new Flute(d); m_frequency = 100.0; m_rate = 0.5; m_jetDelay = 0.0; m_jetReflection = 0.0; m_endReflection = 0.0; } }; //----------------------------------------------------------------------------- // name: Flute_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Flute_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new Flute( 40.0 ); } //----------------------------------------------------------------------------- // name: Flute_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Flute_dtor ) { Flute * f = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); SAFE_DELETE(f); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Flute_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Flute_tick ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Flute_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Flute_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Flute_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_startBlowing ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->startBlowing( f, b->m_rate ); } //----------------------------------------------------------------------------- // name: Flute_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_stopBlowing ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: Flute_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_clear ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: Flute_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_rate ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->m_rate = f; RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Flute_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_rate ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Flute_ctrl_jetDelay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_jetDelay ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setJetDelay( f); RETURN->v_float = (t_CKFLOAT)b->m_jetDelay; } //----------------------------------------------------------------------------- // name: Flute_cget_jetDelay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_jetDelay ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_jetDelay; } //----------------------------------------------------------------------------- // name: Flute_ctrl_jetReflection() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_jetReflection ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setJetReflection( f); RETURN->v_float = (t_CKFLOAT)b->m_jetReflection; } //----------------------------------------------------------------------------- // name: Flute_cget_jetReflection() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_jetReflection ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_jetReflection; } //----------------------------------------------------------------------------- // name: Flute_ctrl_endReflection() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_endReflection ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setEndReflection(f); RETURN->v_float = (t_CKFLOAT)b->m_endReflection; } //----------------------------------------------------------------------------- // name: Flute_cget_endReflection() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_endReflection ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_endReflection; } //----------------------------------------------------------------------------- // name: Flute_ctrl_noiseGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_noiseGain ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 4, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Flute_cget_noiseGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_noiseGain ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Flute_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_vibratoFreq ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setVibratoFreq( f ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Flute_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_vibratoFreq ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Flute_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_vibratoGain ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 1, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Flute_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_vibratoGain ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Flute_ctrl_pressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Flute_ctrl_pressure ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 128, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)b->m_pressure; } //----------------------------------------------------------------------------- // name: Flute_cget_pressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Flute_cget_pressure ) { Flute * b = (Flute *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_pressure; } // ModalBar struct ModalBar_ { ModalBar modalbar; int m_preset; int m_modeIndex; double m_modeRatio; double m_modeRadius; ModalBar_ ( ) { m_preset = 0; m_modeIndex = 0; } }; //----------------------------------------------------------------------------- // name: ModalBar_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( ModalBar_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new ModalBar_(); } //----------------------------------------------------------------------------- // name: ModalBar_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( ModalBar_dtor ) { delete (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: ModalBar_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( ModalBar_tick ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->modalbar.tick(); return TRUE; } //----------------------------------------------------------------------------- // name: ModalBar_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( ModalBar_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_strike() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_strike ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.strike( f ); } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_damp() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_damp ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.damp( f ); } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_clear ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->modalbar.clear(); } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_preset() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_preset ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); int f = GET_CK_INT(ARGS); b->m_preset = f; b->modalbar.setPreset ( f ); RETURN->v_int = (t_CKINT)b->m_preset; } //----------------------------------------------------------------------------- // name: ModalBar_cget_preset() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_preset ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_int = (t_CKINT)b->m_preset; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_strikePosition() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_strikePosition ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.setStrikePosition( f ); RETURN->v_float = (t_CKFLOAT)b->modalbar.strikePosition; } //----------------------------------------------------------------------------- // name: ModalBar_cget_strikePosition() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_strikePosition ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.strikePosition; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_vibratoGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.controlChange( 11, f*128 ); RETURN->v_float = (t_CKFLOAT)b->modalbar.m_vibratoGain; } //----------------------------------------------------------------------------- // name: ModalBar_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_vibratoGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.m_vibratoGain; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_vibratoFreq ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.vibrato->setFrequency( f ); b->modalbar.m_vibratoFreq = b->modalbar.vibrato->m_freq; RETURN->v_float = (t_CKFLOAT)b->modalbar.m_vibratoFreq; } //----------------------------------------------------------------------------- // name: ModalBar_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_vibratoFreq ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.m_vibratoFreq; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_stickHardness() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_stickHardness ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.setStickHardness ( f ); RETURN->v_float = (t_CKFLOAT)b->modalbar.stickHardness; } //----------------------------------------------------------------------------- // name: ModalBar_cget_stickHardness() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_stickHardness ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.stickHardness; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_masterGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_masterGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.setMasterGain( f ); RETURN->v_float = (t_CKFLOAT)b->modalbar.masterGain; } //----------------------------------------------------------------------------- // name: ModalBar_cget_masterGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_masterGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.masterGain; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_directGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_directGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.setDirectGain( f ); RETURN->v_float = (t_CKFLOAT) b->modalbar.directGain; } //----------------------------------------------------------------------------- // name: ModalBar_cget_directGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_directGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.directGain; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_mode() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_mode ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); int i = GET_CK_INT(ARGS); if ( i >= 0 && i < b->modalbar.nModes ) { b->m_modeIndex = i; b->m_modeRatio = b->modalbar.ratios[i]; b->m_modeRadius = b->modalbar.radii[i]; RETURN->v_float = (t_CKFLOAT)b->m_modeIndex; } } //----------------------------------------------------------------------------- // name: ModalBar_cget_mode() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_mode ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_modeIndex; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_modeGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_modeGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.setModeGain( b->m_modeIndex, f ); RETURN->v_float = (t_CKFLOAT)b->modalbar.filters[b->m_modeIndex]->getGain(); } //----------------------------------------------------------------------------- // name: ModalBar_cget_modeGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_modeGain ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.filters[b->m_modeIndex]->getGain(); } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_modeRatio() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_modeRatio ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); if ( b->m_modeIndex >= 0 && b->m_modeIndex < b->modalbar.nModes ) { b->modalbar.setRatioAndRadius( b->m_modeIndex, f , b->m_modeRadius ); b->m_modeRatio = b->modalbar.ratios[b->m_modeIndex]; RETURN->v_float = (t_CKFLOAT) b->m_modeRatio; } } //----------------------------------------------------------------------------- // name: ModalBar_cget_modeRatio() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_modeRatio ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_modeRatio; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_modeRadius() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_modeRadius ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); if( b->m_modeIndex >= 0 && b->m_modeIndex < b->modalbar.nModes ) { b->modalbar.setRatioAndRadius ( b->m_modeIndex, b->m_modeRatio, f ); b->m_modeRadius = b->modalbar.radii[b->m_modeIndex]; RETURN->v_float = (t_CKFLOAT) b->m_modeRadius; } } //----------------------------------------------------------------------------- // name: ModalBar_cget_modeRadius() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_modeRadius ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_modeRadius; } //----------------------------------------------------------------------------- // name: ModalBar_ctrl_volume() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ModalBar_ctrl_volume ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->modalbar.controlChange( 128, f*128 ); RETURN->v_float = (t_CKFLOAT)b->modalbar.m_volume; } //----------------------------------------------------------------------------- // name: ModalBar_cget_volume() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ModalBar_cget_volume ) { ModalBar_ * b = (ModalBar_ *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->modalbar.m_volume; } // Sitar /* struct Sitar_ { Sitar * imp; double m_frequency; Sitar_ ( double d ) { imp = new Sitar(d); m_frequency = 100.0; } };*/ //----------------------------------------------------------------------------- // name: Sitar_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Sitar_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new Sitar( 30.0 ); } //----------------------------------------------------------------------------- // name: Sitar_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Sitar_dtor ) { Sitar * s = (Sitar *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); SAFE_DELETE(s); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Sitar_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Sitar_tick ) { Sitar * b = (Sitar *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Sitar_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Sitar_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Sitar_ctrl_pluck() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Sitar_ctrl_pluck ) { Sitar * b = (Sitar *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->pluck( f ); } //----------------------------------------------------------------------------- // name: Sitar_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Sitar_ctrl_clear ) { Sitar * b = (Sitar *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: Saxofony_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Saxofony_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new Saxofony( 30.0 ); } //----------------------------------------------------------------------------- // name: Saxofony_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Saxofony_dtor ) { Saxofony * d = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); SAFE_DELETE(d); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Saxofony_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Saxofony_tick ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Saxofony_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Saxofony_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_startBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_startBlowing ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->startBlowing( f, b->m_rate ); } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_stopBlowing() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_stopBlowing ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->stopBlowing( f ); } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_clear ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_rate ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->m_rate = f; RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Saxofony_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_rate ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_rate; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_blowPosition() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_blowPosition ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setBlowPosition(f); RETURN->v_float = (t_CKFLOAT)b->position; } //----------------------------------------------------------------------------- // name: Saxofony_cget_blowPosition() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_blowPosition ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->position; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_reed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_reed ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 2, f * 128 ); RETURN->v_float = (t_CKFLOAT)b->m_stiffness; } //----------------------------------------------------------------------------- // name: Saxofony_cget_reed() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_reed ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_stiffness; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_aperture() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_aperture ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 26, f * 128 ); RETURN->v_float = (t_CKFLOAT)b->m_aperture; } //----------------------------------------------------------------------------- // name: Saxofony_cget_aperture() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_aperture ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_aperture; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_noiseGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_noiseGain ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 4, f * 128 ); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Saxofony_cget_noiseGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_noiseGain ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_noiseGain; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_vibratoFreq ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->vibrato->setFrequency( f ); RETURN->v_float = (t_CKFLOAT)b->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: Saxofony_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_vibratoFreq ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_vibratoGain ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 1, f * 128 ); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Saxofony_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_vibratoGain ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Saxofony_ctrl_pressure() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Saxofony_ctrl_pressure ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->controlChange( 128, f * 128 ); RETURN->v_float = (t_CKFLOAT)b->m_pressure; } //----------------------------------------------------------------------------- // name: Saxofony_cget_pressure() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Saxofony_cget_pressure ) { Saxofony * b = (Saxofony *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->m_pressure; } // StifKarp //----------------------------------------------------------------------------- // name: StifKarp_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( StifKarp_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new StifKarp( 30.0 ); } //----------------------------------------------------------------------------- // name: StifKarp_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( StifKarp_dtor ) { delete (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: StifKarp_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( StifKarp_tick ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = b->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: StifKarp_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( StifKarp_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_pluck() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_pluck ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->pluck( f ); } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_clear() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_clear ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); b->clear(); } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_pickupPosition() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_pickupPosition ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setPickupPosition( f ); RETURN->v_float = (t_CKFLOAT)b->pickupPosition; } //----------------------------------------------------------------------------- // name: StifKarp_cget_pickupPosition() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( StifKarp_cget_pickupPosition ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->pickupPosition; } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_stretch() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_stretch ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setStretch( f ); RETURN->v_float = (t_CKFLOAT)b->stretching; } //----------------------------------------------------------------------------- // name: StifKarp_cget_stretch() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( StifKarp_cget_stretch ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->stretching; } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_sustain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_sustain ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setStretch( f ); RETURN->v_float = (t_CKFLOAT)b->stretching; } //----------------------------------------------------------------------------- // name: StifKarp_cget_sustain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( StifKarp_cget_sustain ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->stretching; } //----------------------------------------------------------------------------- // name: StifKarp_ctrl_baseLoopGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( StifKarp_ctrl_baseLoopGain ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); b->setBaseLoopGain( f ); RETURN->v_float = (t_CKFLOAT)b->baseLoopGain; } //----------------------------------------------------------------------------- // name: StifKarp_cget_baseLoopGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( StifKarp_cget_baseLoopGain ) { StifKarp * b = (StifKarp *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)b->baseLoopGain; } // Delay //----------------------------------------------------------------------------- // name: Delay_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Delay_ctor ) { OBJ_MEMBER_UINT(SELF, Delay_offset_data) = (t_CKUINT)new Delay; } //----------------------------------------------------------------------------- // name: Delay_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Delay_dtor ) { delete (Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data); OBJ_MEMBER_UINT(SELF, Delay_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Delay_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Delay_tick ) { *out = (SAMPLE)((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: Delay_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Delay_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: Delay_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Delay_ctrl_delay ) { ((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->setDelay( (long)(GET_NEXT_DUR(ARGS)+.5) ); RETURN->v_dur = (t_CKDUR)((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: Delay_cget_delay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Delay_cget_delay ) { RETURN->v_dur = (t_CKDUR)((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: Delay_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Delay_ctrl_max ) { Delay * delay = (Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data); t_CKFLOAT val = (t_CKFLOAT)delay->getDelay(); t_CKDUR max = GET_NEXT_DUR(ARGS); delay->set( (long)(val+.5), (long)(max+1.5) ); RETURN->v_dur = (t_CKDUR)((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->length-1.0; } //----------------------------------------------------------------------------- // name: Delay_cget_max() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Delay_cget_max ) { RETURN->v_dur = (t_CKDUR)((Delay *)OBJ_MEMBER_UINT(SELF, Delay_offset_data))->length-1.0; } // DelayA //----------------------------------------------------------------------------- // name: DelayA_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( DelayA_ctor ) { OBJ_MEMBER_UINT(SELF, DelayA_offset_data) = (t_CKUINT)new DelayA; } //----------------------------------------------------------------------------- // name: DelayA_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( DelayA_dtor ) { delete (DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data); OBJ_MEMBER_UINT(SELF, DelayA_offset_data) = 0; } //----------------------------------------------------------------------------- // name: DelayA_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( DelayA_tick ) { *out = (SAMPLE)((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: DelayA_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( DelayA_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: DelayA_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( DelayA_ctrl_delay ) { ((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->setDelay( GET_NEXT_DUR(ARGS) ); RETURN->v_dur = (t_CKDUR)((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: DelayA_cget_delay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( DelayA_cget_delay ) { RETURN->v_dur = (t_CKDUR)((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: DelayA_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( DelayA_ctrl_max ) { DelayA * delay = (DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data); t_CKDUR val = (t_CKDUR)delay->getDelay(); t_CKDUR max = GET_NEXT_DUR(ARGS); delay->set( val, (long)(max+1.5) ); RETURN->v_dur = (t_CKDUR)((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->length-1.0; } //----------------------------------------------------------------------------- // name: DelayA_cget_max() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( DelayA_cget_max ) { RETURN->v_dur = (t_CKDUR)((DelayA *)OBJ_MEMBER_UINT(SELF, DelayA_offset_data))->length-1.0; } // DelayL //----------------------------------------------------------------------------- // name: DelayL_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( DelayL_ctor ) { OBJ_MEMBER_UINT(SELF, DelayL_offset_data) = (t_CKUINT)new DelayL; } //----------------------------------------------------------------------------- // name: DelayL_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( DelayL_dtor ) { delete (DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data); OBJ_MEMBER_UINT(SELF, DelayL_offset_data) = 0; } //----------------------------------------------------------------------------- // name: DelayL_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( DelayL_tick ) { *out = (SAMPLE)((DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data))->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: DelayL_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( DelayL_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: DelayL_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( DelayL_ctrl_delay ) { ((DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data))->setDelay( GET_NEXT_DUR(ARGS) ); RETURN->v_dur = (t_CKDUR)((DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: DelayL_cget_delay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( DelayL_cget_delay ) { RETURN->v_dur = (t_CKDUR)((DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: DelayL_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( DelayL_ctrl_max ) { DelayL * delay = (DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data); t_CKDUR val = (t_CKDUR)delay->getDelay(); t_CKDUR max = GET_NEXT_DUR(ARGS); delay->set( val, (long)(max+1.5) ); RETURN->v_dur = (t_CKDUR)delay->length-1.0; } //----------------------------------------------------------------------------- // name: DelayL_cget_max() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( DelayL_cget_max ) { RETURN->v_dur = (t_CKDUR)((DelayL *)OBJ_MEMBER_UINT(SELF, DelayL_offset_data))->length-1.0; } // Echo //----------------------------------------------------------------------------- // name: Echo_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Echo_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Echo_offset_data) = (t_CKUINT)new Echo( Stk::sampleRate() / 2.0 ); } //----------------------------------------------------------------------------- // name: Echo_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Echo_dtor ) { delete (Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data); OBJ_MEMBER_UINT(SELF, Echo_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Echo_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Echo_tick ) { *out = (SAMPLE)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: Echo_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Echo_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: Echo_ctrl_delay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Echo_ctrl_delay ) { ((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->setDelay( GET_NEXT_DUR(ARGS) ); RETURN->v_dur = (t_CKDUR)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: Echo_cget_delay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Echo_cget_delay ) { RETURN->v_dur = (t_CKDUR)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->getDelay(); } //----------------------------------------------------------------------------- // name: Echo_ctrl_max() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Echo_ctrl_max ) { ((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->set( GET_NEXT_DUR(ARGS) ); RETURN->v_dur = (t_CKDUR)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->length; } //----------------------------------------------------------------------------- // name: Echo_cget_max() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Echo_cget_max ) { RETURN->v_dur = (t_CKDUR)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->length; } //----------------------------------------------------------------------------- // name: Echo_ctrl_mix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Echo_ctrl_mix ) { ((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->setEffectMix( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->effectMix; } //----------------------------------------------------------------------------- // name: Echo_cget_mix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Echo_cget_mix ) { RETURN->v_float = (t_CKFLOAT)((Echo *)OBJ_MEMBER_UINT(SELF, Echo_offset_data))->effectMix; } //----------------------------------------------------------------------------- // name: Envelope - import // desc: .. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: Envelope_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Envelope_ctor ) { OBJ_MEMBER_UINT(SELF, Envelope_offset_data) = (t_CKUINT)new Envelope; } //----------------------------------------------------------------------------- // name: Envelope_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Envelope_dtor ) { delete (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); OBJ_MEMBER_UINT(SELF, Envelope_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Envelope_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Envelope_tick ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); *out = in * d->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Envelope_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Envelope_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_time() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_time ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setTime( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = d->m_time; } //----------------------------------------------------------------------------- // name: Envelope_cget_time() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Envelope_cget_time ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = d->m_time; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_duration() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_duration ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setTime( GET_NEXT_FLOAT(ARGS) / Stk::sampleRate() ); RETURN->v_float = 1.0 / d->rate; } //----------------------------------------------------------------------------- // name: Envelope_cget_duration() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Envelope_cget_duration ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = 1.0 / d->rate; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_rate ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setRate( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->rate; } //----------------------------------------------------------------------------- // name: Envelope_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Envelope_cget_rate ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->rate; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_target() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_target ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setTarget( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->target; } //----------------------------------------------------------------------------- // name: Envelope_cget_target() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Envelope_cget_target ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->target; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_value() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_value ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setValue( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->value; } //----------------------------------------------------------------------------- // name: Envelope_cget_value() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Envelope_cget_value ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->value; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_keyOn0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_keyOn0 ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->keyOn(); RETURN->v_int = 1; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_keyOn() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_keyOn ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); if( GET_NEXT_INT(ARGS) ) { d->keyOn(); RETURN->v_int = 1; } else { d->keyOff(); RETURN->v_int = 0; } } //----------------------------------------------------------------------------- // name: Envelope_ctrl_keyOff0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_keyOff0 ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->keyOff(); RETURN->v_int = 1; } //----------------------------------------------------------------------------- // name: Envelope_ctrl_keyOff() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Envelope_ctrl_keyOff ) { Envelope * d = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); if( !GET_NEXT_INT(ARGS) ) { d->keyOn(); RETURN->v_int = 0; } else { d->keyOff(); RETURN->v_int = 1; } } //----------------------------------------------------------------------------- // name: ADSR - import // desc: .. //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // name: ADSR_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( ADSR_ctor ) { // TODO: fix this horrid thing Envelope * e = (Envelope *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); SAFE_DELETE(e); OBJ_MEMBER_UINT(SELF, Envelope_offset_data) = (t_CKUINT)new ADSR; } //----------------------------------------------------------------------------- // name: ADSR_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( ADSR_dtor ) { delete (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); OBJ_MEMBER_UINT(SELF, Envelope_offset_data) = 0; } //----------------------------------------------------------------------------- // name: ADSR_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( ADSR_tick ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); *out = in * d->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: ADSR_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( ADSR_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: ADSR_ctrl_attackTime() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_attackTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); t_CKDUR t = GET_NEXT_DUR(ARGS); d->setAttackTime( t / Stk::sampleRate() ); RETURN->v_dur = t; } //----------------------------------------------------------------------------- // name: ADSR_cget_attackTime() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_attackTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_dur = d->getAttackTime(); } //----------------------------------------------------------------------------- // name: ADSR_ctrl_attackRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_attackRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setAttackRate( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->attackRate; } //----------------------------------------------------------------------------- // name: ADSR_cget_attackRate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_attackRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->attackRate; } //----------------------------------------------------------------------------- // name: ADSR_ctrl_decayTime() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_decayTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); t_CKDUR t = GET_NEXT_DUR(ARGS); d->setDecayTime( t / Stk::sampleRate() ); RETURN->v_dur = t; } //----------------------------------------------------------------------------- // name: ADSR_cget_decayTime() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_decayTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_dur = d->getDecayTime(); } //----------------------------------------------------------------------------- // name: ADSR_ctrl_decayRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_decayRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setDecayRate( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->decayRate; } //----------------------------------------------------------------------------- // name: ADSR_cget_decayRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_decayRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->decayRate; } //----------------------------------------------------------------------------- // name: ADSR_ctrl_sustainLevel() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_sustainLevel ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setSustainLevel( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->sustainLevel; } //----------------------------------------------------------------------------- // name: ADSR_cget_sustainLevel() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_sustainLevel ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->sustainLevel; } //----------------------------------------------------------------------------- // name: ADSR_ctrl_releaseTime() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_releaseTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); t_CKDUR t = GET_NEXT_DUR(ARGS); d->setReleaseTime( t / Stk::sampleRate() ); RETURN->v_dur = t; } //----------------------------------------------------------------------------- // name: ADSR_cget_releaseTime() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_releaseTime ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_dur = d->getReleaseTime(); } //----------------------------------------------------------------------------- // name: ADSR_ctrl_releaseRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_releaseRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); d->setReleaseRate( GET_NEXT_FLOAT(ARGS) ); RETURN->v_float = (t_CKFLOAT)d->releaseRate; } //----------------------------------------------------------------------------- // name: ADSR_cget_releaseRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_releaseRate ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_float = (t_CKFLOAT)d->releaseRate; } //----------------------------------------------------------------------------- // name: ADSR_cget_state() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CGET( ADSR_cget_state ) { ADSR * d = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); RETURN->v_int = (t_CKINT) d->state; } //----------------------------------------------------------------------------- // name: ADSR_ctrl_set() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_set ) { ADSR * e = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); t_CKFLOAT a = GET_NEXT_FLOAT(ARGS); t_CKFLOAT d = GET_NEXT_FLOAT(ARGS); t_CKFLOAT s = GET_NEXT_FLOAT(ARGS); t_CKFLOAT r = GET_NEXT_FLOAT(ARGS); e->setAttackTime( a ); e->setDecayTime( d ); e->setSustainLevel( s ); e->setReleaseTime( r ); } //----------------------------------------------------------------------------- // name: ADSR_ctrl_set2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( ADSR_ctrl_set2 ) { ADSR * e = (ADSR *)OBJ_MEMBER_UINT(SELF, Envelope_offset_data); t_CKDUR a = GET_NEXT_DUR(ARGS); t_CKDUR d = GET_NEXT_DUR(ARGS); t_CKFLOAT s = GET_NEXT_FLOAT(ARGS); t_CKDUR r = GET_NEXT_DUR(ARGS); e->setAttackTime( a / Stk::sampleRate() ); e->setDecayTime( d / Stk::sampleRate() ); e->setSustainLevel( s ); e->setReleaseTime( r / Stk::sampleRate() ); } // FilterStk //----------------------------------------------------------------------------- // name: FilterStk_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( FilterStk_ctor ) { OBJ_MEMBER_UINT(SELF, FilterStk_offset_data) = (t_CKUINT)new FilterStk; } //----------------------------------------------------------------------------- // name: FilterStk_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( FilterStk_dtor ) { delete (FilterStk *)OBJ_MEMBER_UINT(SELF, FilterStk_offset_data); OBJ_MEMBER_UINT(SELF, FilterStk_offset_data) = 0; } //----------------------------------------------------------------------------- // name: FilterStk_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( FilterStk_tick ) { FilterStk * d = (FilterStk *)OBJ_MEMBER_UINT(SELF, FilterStk_offset_data); *out = d->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: FilterStk_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( FilterStk_pmsg ) { return FALSE; } //----------------------------------------------------------------------------- // name: FilterStk_ctrl_coefs() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FilterStk_ctrl_coefs ) { // FilterStk * d = (FilterStk *)OBJ_MEMBER_UINT(SELF, FilterStk_offset_data); fprintf( stderr, "FilterStk.coefs :: not implemented\n" ); } //----------------------------------------------------------------------------- // name: OnePole_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( OnePole_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, OnePole_offset_data) = (t_CKUINT)new OnePole(); } //----------------------------------------------------------------------------- // name: OnePole_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( OnePole_dtor ) { delete (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); OBJ_MEMBER_UINT(SELF, OnePole_offset_data) = 0; } //----------------------------------------------------------------------------- // name: OnePole_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( OnePole_tick ) { OnePole * m = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); *out = m->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: OnePole_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( OnePole_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: OnePole_ctrl_a1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OnePole_ctrl_a1 ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setA1( f ); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: OnePole_cget_a1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OnePole_cget_a1 ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: OnePole_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OnePole_ctrl_b0 ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB0( f ); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: OnePole_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OnePole_cget_b0 ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: OnePole_ctrl_pole() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OnePole_ctrl_pole ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setPole( f ); RETURN->v_float = (t_CKFLOAT) -filter->a[1]; } //----------------------------------------------------------------------------- // name: OnePole_cget_pole() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OnePole_cget_pole ) { OnePole * filter = (OnePole *)OBJ_MEMBER_UINT(SELF, OnePole_offset_data); RETURN->v_float = (t_CKFLOAT) -filter->a[1]; } //TwoPole functions //----------------------------------------------------------------------------- // name: TwoPole_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( TwoPole_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, TwoPole_offset_data) = (t_CKUINT)new TwoPole(); } //----------------------------------------------------------------------------- // name: TwoPole_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( TwoPole_dtor ) { delete (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); OBJ_MEMBER_UINT(SELF, TwoPole_offset_data) = 0; } //----------------------------------------------------------------------------- // name: TwoPole_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( TwoPole_tick ) { TwoPole * m = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); *out = m->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: TwoPole_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( TwoPole_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_a1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_a1 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setA1( f ); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: TwoPole_cget_a1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_a1 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_a2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_a2 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setA2( f ); RETURN->v_float = (t_CKFLOAT) filter->a[2]; } //----------------------------------------------------------------------------- // name: TwoPole_cget_a2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_a2 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->a[2]; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_b0 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB0( f ); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: TwoPole_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_b0 ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_freq ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->ck_setResFreq( f ); RETURN->v_float = (t_CKFLOAT) filter->m_resFreq; } //----------------------------------------------------------------------------- // name: TwoPole_cget_freq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_freq ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->m_resFreq; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_radius() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_radius ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->ck_setResRad( f ); RETURN->v_float = (t_CKFLOAT) filter->m_resRad; } //----------------------------------------------------------------------------- // name: TwoPole_cget_radius() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_radius ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_float = (t_CKFLOAT) filter->m_resRad; } //----------------------------------------------------------------------------- // name: TwoPole_ctrl_norm() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoPole_ctrl_norm ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); bool b = ( GET_CK_INT(ARGS) != 0 ); filter->ck_setResNorm( b ); RETURN->v_int = (t_CKINT) filter->m_resNorm; } //----------------------------------------------------------------------------- // name: TwoPole_cget_norm() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoPole_cget_norm ) { TwoPole * filter = (TwoPole *)OBJ_MEMBER_UINT(SELF, TwoPole_offset_data); RETURN->v_int = (t_CKINT) filter->m_resNorm; } //OneZero functions //----------------------------------------------------------------------------- // name: OneZero_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( OneZero_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, OneZero_offset_data) = (t_CKUINT) new OneZero(); } //----------------------------------------------------------------------------- // name: OneZero_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( OneZero_dtor ) { delete (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); OBJ_MEMBER_UINT(SELF, OneZero_offset_data) = 0; } //----------------------------------------------------------------------------- // name: OneZero_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( OneZero_tick ) { OneZero * m = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); *out = m->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: OneZero_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( OneZero_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: OneZero_ctrl_zero() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OneZero_ctrl_zero ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setZero( f ); double zeeroo = ( filter->b[0] == 0 ) ? 0 : -filter->b[1] / filter->b[0]; RETURN->v_float = (t_CKFLOAT) zeeroo; } //----------------------------------------------------------------------------- // name: OneZero_cget_zero() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OneZero_cget_zero ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); double zeeroo = ( filter->b[0] == 0 ) ? 0 : -filter->b[1] / filter->b[0]; RETURN->v_float = (t_CKFLOAT)zeeroo; } //----------------------------------------------------------------------------- // name: OneZero_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OneZero_ctrl_b0 ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB0( f ); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: OneZero_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OneZero_cget_b0 ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: OneZero_ctrl_b1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( OneZero_ctrl_b1 ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB1( f ); RETURN->v_float = (t_CKFLOAT) filter->b[1]; } //----------------------------------------------------------------------------- // name: OneZero_cget_b1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( OneZero_cget_b1 ) { OneZero * filter = (OneZero *)OBJ_MEMBER_UINT(SELF, OneZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[1]; } //TwoZero functions //----------------------------------------------------------------------------- // name: TwoZero_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( TwoZero_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, TwoZero_offset_data) = (t_CKUINT)new TwoZero(); } //----------------------------------------------------------------------------- // name: TwoZero_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( TwoZero_dtor ) { delete (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); OBJ_MEMBER_UINT(SELF, TwoZero_offset_data) = 0; } //----------------------------------------------------------------------------- // name: TwoZero_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( TwoZero_tick ) { TwoZero * m = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); *out = m->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: TwoZero_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( TwoZero_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: TwoZero_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoZero_ctrl_b0 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB0( f ); } //----------------------------------------------------------------------------- // name: TwoZero_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoZero_cget_b0 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: TwoZero_ctrl_b1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoZero_ctrl_b1 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB1( f ); } //----------------------------------------------------------------------------- // name: TwoZero_cget_b1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoZero_cget_b1 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[1]; } //----------------------------------------------------------------------------- // name: TwoZero_ctrl_b2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoZero_ctrl_b2 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB2( f ); } //----------------------------------------------------------------------------- // name: TwoZero_cget_b2() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoZero_cget_b2 ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[2]; } //----------------------------------------------------------------------------- // name: TwoZero_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoZero_ctrl_freq ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->ck_setNotchFreq( f ); } //----------------------------------------------------------------------------- // name: TwoZero_cget_freq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoZero_cget_freq ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->m_notchFreq; } //----------------------------------------------------------------------------- // name: TwoZero_ctrl_radius() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( TwoZero_ctrl_radius ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->ck_setNotchRad( f ); } //----------------------------------------------------------------------------- // name: TwoZero_cget_radius() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( TwoZero_cget_radius ) { TwoZero * filter = (TwoZero *)OBJ_MEMBER_UINT(SELF, TwoZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->m_notchRad; } //PoleZero functions //----------------------------------------------------------------------------- // name: PoleZero_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( PoleZero_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, PoleZero_offset_data) = (t_CKUINT) new PoleZero(); } //----------------------------------------------------------------------------- // name: PoleZero_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( PoleZero_dtor ) { delete (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); OBJ_MEMBER_UINT(SELF, PoleZero_offset_data) = 0; } //----------------------------------------------------------------------------- // name: PoleZero_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( PoleZero_tick ) { PoleZero * m = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); *out = m->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: PoleZero_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( PoleZero_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: PoleZero_ctrl_a1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PoleZero_ctrl_a1 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setA1( f ); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: PoleZero_cget_a1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PoleZero_cget_a1 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->a[1]; } //----------------------------------------------------------------------------- // name: PoleZero_ctrl_b0() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PoleZero_ctrl_b0 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB0( f ); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: PoleZero_cget_b0() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PoleZero_cget_b0 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: PoleZero_ctrl_b1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PoleZero_ctrl_b1 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setB1( f ); RETURN->v_float = (t_CKFLOAT) filter->b[1]; } //----------------------------------------------------------------------------- // name: PoleZero_cget_b1() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PoleZero_cget_b1 ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[1]; } //----------------------------------------------------------------------------- // name: PoleZero_ctrl_allpass() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PoleZero_ctrl_allpass ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setAllpass( f ); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: PoleZero_cget_allpass() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PoleZero_cget_allpass ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); RETURN->v_float = (t_CKFLOAT) filter->b[0]; } //----------------------------------------------------------------------------- // name: PoleZero_ctrl_blockZero() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PoleZero_ctrl_blockZero ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); filter->setBlockZero( f ); RETURN->v_float = (t_CKFLOAT) -filter->a[1]; } //----------------------------------------------------------------------------- // name: PoleZero_cget_blockZero() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PoleZero_cget_blockZero ) { PoleZero * filter = (PoleZero *)OBJ_MEMBER_UINT(SELF, PoleZero_offset_data); RETURN->v_float = (t_CKFLOAT) -filter->a[1]; } //FM functions //----------------------------------------------------------------------------- // name: FM_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( FM_ctor ) { OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; // fprintf(stderr,"[chuck](via STK): error : FM is virtual!\n"); } //----------------------------------------------------------------------------- // name: FM_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( FM_dtor ) { // delete (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); // fprintf(stderr,"error : FM is virtual!\n"); } //----------------------------------------------------------------------------- // name: FM_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( FM_tick ) { FM * m = (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); fprintf(stderr,"[chuck](via STK): error : FM tick is virtual!\n"); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: FM_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( FM_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: FM_ctrl_modDepth() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_ctrl_modDepth ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); fm->setModulationDepth( f ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: FM_cget_modDepth() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_cget_modDepth ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); RETURN->v_float = fm->modDepth; } //----------------------------------------------------------------------------- // name: FM_ctrl_modSpeed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_ctrl_modSpeed ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); fm->setModulationSpeed( f ); RETURN->v_float = fm->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: FM_ctrl_modSpeed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_cget_modSpeed ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); RETURN->v_float = fm->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: FM_ctrl_control1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_ctrl_control1 ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); fm->setControl1( f ); RETURN->v_float = fm->control1 / 2.0; } //----------------------------------------------------------------------------- // name: FM_cget_control1() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_cget_control1 ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); RETURN->v_float = fm->control1 / 2.0; } //----------------------------------------------------------------------------- // name: FM_ctrl_control2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_ctrl_control2 ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); fm->setControl2( f ); RETURN->v_float = fm->control2 / 2.0; } //----------------------------------------------------------------------------- // name: FM_cget_control2() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_cget_control2 ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); RETURN->v_float = fm->control2 / 2.0; } //----------------------------------------------------------------------------- // name: FM_ctrl_afterTouch() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_ctrl_afterTouch ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); fm->controlChange( __SK_AfterTouch_Cont_, f * 128.0 ); RETURN->v_float = fm->adsr[1]->target; } //----------------------------------------------------------------------------- // name: FM_cget_afterTouch() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FM_cget_afterTouch ) { FM * fm= (FM *)OBJ_MEMBER_UINT(SELF, FM_offset_data); RETURN->v_float = fm->adsr[1]->target; } //----------------------------------------------------------------------------- // name: BeeThree_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( BeeThree_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new BeeThree(); } //----------------------------------------------------------------------------- // name: BeeThree_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( BeeThree_dtor ) { delete (BeeThree *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: BeeThree_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( BeeThree_tick ) { BeeThree * m = (BeeThree *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: BeeThree_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( BeeThree_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: FMVoices_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( FMVoices_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new FMVoices(); } //----------------------------------------------------------------------------- // name: FMVoices_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( FMVoices_dtor ) { delete (FMVoices *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: FMVoices_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( FMVoices_tick ) { FMVoices * m = (FMVoices *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: FMVoices_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( FMVoices_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: FMVoices_ctrl_vowel() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_ctrl_vowel ) { FMVoices * voc= (FMVoices *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); voc->controlChange( __SK_Breath_, f * 128.0 ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: FMVoices_cget_vowel() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_cget_vowel ) { } //----------------------------------------------------------------------------- // name: FMVoices_ctrl_spectralTilt() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_ctrl_spectralTilt ) { FMVoices * voc= (FMVoices *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); voc->controlChange( __SK_FootControl_, f * 128.0); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: FMVoices_cget_spectralTilt() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_cget_spectralTilt ) { } //----------------------------------------------------------------------------- // name: FMVoices_ctrl_adsrTarget() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_ctrl_adsrTarget ) { FMVoices * voc= (FMVoices *)OBJ_MEMBER_UINT(SELF, FM_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); voc->controlChange( __SK_AfterTouch_Cont_, f * 128.0); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: FMVoices_cget_adsrTarget() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( FMVoices_cget_adsrTarget ) { } //----------------------------------------------------------------------------- // name: HevyMetl_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( HevyMetl_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new HevyMetl(); } //----------------------------------------------------------------------------- // name: HevyMetl_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( HevyMetl_dtor ) { delete (HevyMetl *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: HevyMetl_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( HevyMetl_tick ) { HevyMetl * m = (HevyMetl *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: HevyMetl_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( HevyMetl_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: PercFlut_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( PercFlut_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new PercFlut(); } //----------------------------------------------------------------------------- // name: PercFlut_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( PercFlut_dtor ) { delete (PercFlut *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: PercFlut_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( PercFlut_tick ) { PercFlut * m = (PercFlut *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: PercFlut_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( PercFlut_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Rhodey_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Rhodey_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new Rhodey(); } //----------------------------------------------------------------------------- // name: Rhodey_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Rhodey_dtor ) { delete (Rhodey *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Rhodey_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Rhodey_tick ) { Rhodey * m = (Rhodey *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Rhodey_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Rhodey_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: TubeBell_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( TubeBell_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT) new TubeBell(); } //----------------------------------------------------------------------------- // name: TubeBell_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( TubeBell_dtor ) { delete (TubeBell *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: TubeBell_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( TubeBell_tick ) { TubeBell * m = (TubeBell *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: TubeBell_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( TubeBell_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Wurley_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Wurley_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FM_offset_data) = (t_CKUINT)new Wurley(); } //----------------------------------------------------------------------------- // name: Wurley_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Wurley_dtor ) { delete (Wurley *)OBJ_MEMBER_UINT(SELF, FM_offset_data); OBJ_MEMBER_UINT(SELF, FM_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Wurley_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Wurley_tick ) { Wurley * m = (Wurley *)OBJ_MEMBER_UINT(SELF, FM_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Wurley_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Wurley_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: FormSwep_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( FormSwep_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, FormSwep_offset_data) = (t_CKUINT)new FormSwep(); } //----------------------------------------------------------------------------- // name: FormSwep_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( FormSwep_dtor ) { delete (FormSwep *)OBJ_MEMBER_UINT(SELF, FormSwep_offset_data); OBJ_MEMBER_UINT(SELF, FormSwep_offset_data) = 0; } //----------------------------------------------------------------------------- // name: FormSwep_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( FormSwep_tick ) { FormSwep * m = (FormSwep *)OBJ_MEMBER_UINT(SELF, FormSwep_offset_data); *out = m->tick(in); return TRUE; } //----------------------------------------------------------------------------- // name: FormSwep_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( FormSwep_pmsg ) { return TRUE; } //FormSwep requires multiple arguments //to most of its parameters. //----------------------------------------------------------------------------- // name: JCRev_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( JCRev_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, JCRev_offset_data) = (t_CKUINT)new JCRev( 4.0f ); } //----------------------------------------------------------------------------- // name: JCRev_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( JCRev_dtor ) { delete (JCRev *)OBJ_MEMBER_UINT(SELF, JCRev_offset_data); OBJ_MEMBER_UINT(SELF, JCRev_offset_data) = 0; } //----------------------------------------------------------------------------- // name: JCRev_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( JCRev_tick ) { JCRev * j = (JCRev *)OBJ_MEMBER_UINT(SELF, JCRev_offset_data); *out = j->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: JCRev_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( JCRev_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: JCRev_ctrl_mix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( JCRev_ctrl_mix ) { JCRev * j = (JCRev *)OBJ_MEMBER_UINT(SELF, JCRev_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setEffectMix( f ); RETURN->v_float = (t_CKFLOAT) j->effectMix; } //----------------------------------------------------------------------------- // name: JCRev_cget_mix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( JCRev_cget_mix ) { JCRev * j = (JCRev *)OBJ_MEMBER_UINT(SELF, JCRev_offset_data); RETURN->v_float = (t_CKFLOAT) j->effectMix; } //----------------------------------------------------------------------------- // name: Mandolin_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Mandolin_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT) new Mandolin( 50.0f ); } //----------------------------------------------------------------------------- // name: Mandolin_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Mandolin_dtor ) { delete (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Mandolin_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Mandolin_tick ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Mandolin_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Mandolin_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_pluck() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_pluck ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->pluck( f ); } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_pluckPos() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_pluckPos ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->setPluckPosition( f ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: Mandolin_cget_pluckPos() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Mandolin_cget_pluckPos ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)m->pluckPosition; } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_bodySize() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_bodySize ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->setBodySize( f ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: Mandolin_cget_bodySize() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Mandolin_cget_bodySize ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)m->m_bodySize; } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_stringDamping() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_stringDamping ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); // m->setBaseLoopGain( f ); m->setBaseLoopGain( 0.97f + f * 0.03f ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: Mandolin_cget_stringDamping() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Mandolin_cget_stringDamping ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)m->baseLoopGain; } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_stringDetune() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_stringDetune ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); // m->setDetune( f ); m->setDetune( 1.0f - 0.1f * f ); RETURN->v_float = f; } //----------------------------------------------------------------------------- // name: Mandolin_cget_stringDetune() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Mandolin_cget_stringDetune ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)m->detuning; } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_afterTouch() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_afterTouch ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); // not sure what this does in stk version so we'll just call controlChange m->controlChange( __SK_AfterTouch_Cont_, f * 128.0 ); } //----------------------------------------------------------------------------- // name: Mandolin_ctrl_bodyIR() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Mandolin_ctrl_bodyIR ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); Chuck_String * str = GET_NEXT_STRING(ARGS); m->setBodyIR( str->str.c_str(), strstr(str->str.c_str(), ".raw") != NULL ); RETURN->v_string = str; } //----------------------------------------------------------------------------- // name: Mandolin_cget_bodyIR() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CGET( Mandolin_cget_bodyIR ) { Mandolin * m = (Mandolin *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_string = &(m->soundfile[0]->str_filename); } // Modulate //----------------------------------------------------------------------------- // name: Modulate_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Modulate_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Modulate_offset_data) = (t_CKUINT) new Modulate( ); } //----------------------------------------------------------------------------- // name: Modulate_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Modulate_dtor ) { delete (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); OBJ_MEMBER_UINT(SELF, Modulate_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Modulate_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Modulate_tick ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); *out = j->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Modulate_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Modulate_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Modulate_ctrl_vibratoRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Modulate_ctrl_vibratoRate ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setVibratoRate( f ); RETURN->v_float = (t_CKFLOAT) j->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: Modulate_cget_vibratoRate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Modulate_cget_vibratoRate ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); RETURN->v_float = (t_CKFLOAT) j->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: Modulate_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Modulate_ctrl_vibratoGain ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setVibratoGain( f ); RETURN->v_float = (t_CKFLOAT) j->vibratoGain; } //----------------------------------------------------------------------------- // name: Modulate_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Modulate_cget_vibratoGain ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); RETURN->v_float = (t_CKFLOAT) j->vibratoGain; } //----------------------------------------------------------------------------- // name: Modulate_ctrl_randomGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Modulate_ctrl_randomGain ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setRandomGain(f ); RETURN->v_float = (t_CKFLOAT) j->randomGain; } //----------------------------------------------------------------------------- // name: Modulate_cget_randomGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Modulate_cget_randomGain ) { Modulate * j = (Modulate *)OBJ_MEMBER_UINT(SELF, Modulate_offset_data); RETURN->v_float = (t_CKFLOAT) j->randomGain; } //----------------------------------------------------------------------------- // name: Moog_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Moog_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new Moog(); } //----------------------------------------------------------------------------- // name: Moog_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Moog_dtor ) { delete (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Moog_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Moog_tick ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Moog_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Moog_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Moog_ctrl_modSpeed() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_modSpeed ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->setModulationSpeed(f); RETURN->v_float = (t_CKFLOAT) m->loops[1]->m_freq; } //----------------------------------------------------------------------------- // name: Moog_cget_modSpeed() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_modSpeed ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) m->loops[1]->m_freq; } //----------------------------------------------------------------------------- // name: Moog_ctrl_modDepth() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_modDepth ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->setModulationDepth(f); RETURN->v_float = (t_CKFLOAT) m->modDepth * 2.0; } //----------------------------------------------------------------------------- // name: Moog_cget_modDepth() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_modDepth ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) m->modDepth * 2.0; } //----------------------------------------------------------------------------- // name: Moog_ctrl_filterQ() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_filterQ ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->controlChange( __SK_FilterQ_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) 10.0 * ( m->filterQ - 0.80 ); } //----------------------------------------------------------------------------- // name: Moog_cget_filterQ() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_filterQ ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) 10.0 * ( m->filterQ - 0.80 ); } //----------------------------------------------------------------------------- // name: Moog_ctrl_filterSweepRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_filterSweepRate ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->controlChange( __SK_FilterSweepRate_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) m->filterRate * 5000; } //----------------------------------------------------------------------------- // name: Moog_cget_filterSweepRate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_filterSweepRate ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) m->filterRate * 5000; } //----------------------------------------------------------------------------- // name: Moog_ctrl_afterTouch() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_afterTouch ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->controlChange( __SK_AfterTouch_Cont_, f * 128.0 ); } //----------------------------------------------------------------------------- // name: Moog_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_vibratoFreq ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->setModulationSpeed(f); RETURN->v_float = (t_CKFLOAT)m->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Moog_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_vibratoFreq ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)m->m_vibratoFreq; } //----------------------------------------------------------------------------- // name: Moog_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_vibratoGain ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->controlChange( __SK_ModWheel_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) m->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Moog_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_vibratoGain ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) m->m_vibratoGain; } //----------------------------------------------------------------------------- // name: Moog_ctrl_volume() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Moog_ctrl_volume ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); m->controlChange( __SK_AfterTouch_Cont_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) m->m_volume; } //----------------------------------------------------------------------------- // name: Moog_cget_volume() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Moog_cget_volume ) { Moog * m = (Moog *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) m->m_volume; } // NRev //----------------------------------------------------------------------------- // name: NRev_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( NRev_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, NRev_offset_data) = (t_CKUINT)new NRev( 4.0f ); } //----------------------------------------------------------------------------- // name: NRev_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( NRev_dtor ) { delete (NRev *)OBJ_MEMBER_UINT(SELF, NRev_offset_data); OBJ_MEMBER_UINT(SELF, NRev_offset_data) = 0; } //----------------------------------------------------------------------------- // name: NRev_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( NRev_tick ) { NRev * j = (NRev *)OBJ_MEMBER_UINT(SELF, NRev_offset_data); *out = j->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: NRev_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( NRev_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: NRev_ctrl_mix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( NRev_ctrl_mix ) { NRev * j = (NRev *)OBJ_MEMBER_UINT(SELF, NRev_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setEffectMix( f ); RETURN->v_float = (t_CKFLOAT) j->effectMix; } //----------------------------------------------------------------------------- // name: NRev_cget_mix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( NRev_cget_mix ) { NRev * j = (NRev *)OBJ_MEMBER_UINT(SELF, NRev_offset_data); RETURN->v_float = (t_CKFLOAT) j->effectMix; } // PitShift //----------------------------------------------------------------------------- // name: PitShift_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( PitShift_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, PitShift_offset_data) = (t_CKUINT)new PitShift( ); } //----------------------------------------------------------------------------- // name: PitShift_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( PitShift_dtor ) { delete (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); OBJ_MEMBER_UINT(SELF, PitShift_offset_data) = 0; } //----------------------------------------------------------------------------- // name: PitShift_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( PitShift_tick ) { PitShift * p = (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); *out = p->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: PitShift_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( PitShift_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: PitShift_ctrl_shift() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PitShift_ctrl_shift ) { PitShift * p = (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setShift( f ); RETURN->v_float = (t_CKFLOAT) 1.0 - p->rate; } //----------------------------------------------------------------------------- // name: PitShift_cget_shift() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PitShift_cget_shift ) { PitShift * p = (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); RETURN->v_float = (t_CKFLOAT) 1.0 - p->rate; } //----------------------------------------------------------------------------- // name: PitShift_ctrl_effectMix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PitShift_ctrl_effectMix ) { PitShift * p = (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); p->setEffectMix( f ); RETURN->v_float = (t_CKFLOAT) p->effectMix; } //----------------------------------------------------------------------------- // name: PitShift_cget_effectMix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PitShift_cget_effectMix ) { PitShift * p = (PitShift *)OBJ_MEMBER_UINT(SELF, PitShift_offset_data); RETURN->v_float = (t_CKFLOAT) p->effectMix; } // PRCRev //----------------------------------------------------------------------------- // name: PRCRev_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( PRCRev_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, PRCRev_offset_data) = (t_CKUINT)new PRCRev( 4.0f ); } //----------------------------------------------------------------------------- // name: PRCRev_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( PRCRev_dtor ) { delete (PRCRev *)OBJ_MEMBER_UINT(SELF, PRCRev_offset_data); OBJ_MEMBER_UINT(SELF, PRCRev_offset_data) = 0; } //----------------------------------------------------------------------------- // name: PRCRev_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( PRCRev_tick ) { PRCRev * j = (PRCRev *)OBJ_MEMBER_UINT(SELF, PRCRev_offset_data); *out = j->tick( in ); return TRUE; } //----------------------------------------------------------------------------- // name: PRCRev_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( PRCRev_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: PRCRev_ctrl_mix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( PRCRev_ctrl_mix ) { PRCRev * j = (PRCRev *)OBJ_MEMBER_UINT(SELF, PRCRev_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); j->setEffectMix( f ); RETURN->v_float = (t_CKFLOAT)j->effectMix; } //----------------------------------------------------------------------------- // name: PRCRev_cget_mix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( PRCRev_cget_mix ) { PRCRev * j = (PRCRev *)OBJ_MEMBER_UINT(SELF, PRCRev_offset_data); RETURN->v_float = (t_CKFLOAT)j->effectMix; } //----------------------------------------------------------------------------- // name: Shakers_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Shakers_ctor ) { OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new Shakers; } //----------------------------------------------------------------------------- // name: Shakers_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( Shakers_dtor ) { delete (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: Shakers_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( Shakers_tick ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = s->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: Shakers_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( Shakers_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_which() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_which ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKINT c = GET_CK_INT(ARGS); s->setupNum( c ); RETURN->v_int = (t_CKINT)s->m_noteNum; } //----------------------------------------------------------------------------- // name: Shakers_cget_which() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Shakers_cget_which ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_int = (t_CKINT)s->m_noteNum; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_energy() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_energy ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT e = GET_NEXT_FLOAT(ARGS); s->controlChange( 2, e * 128.0 ); s->m_energy = e; RETURN->v_float = (t_CKFLOAT)s->m_energy; } //----------------------------------------------------------------------------- // name: Shakers_cget_energy() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Shakers_cget_energy ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)s->m_energy; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_decay() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_decay ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT e = GET_NEXT_FLOAT(ARGS); s->controlChange( 4, e * 128.0 ); s->m_decay = e; RETURN->v_float = (t_CKFLOAT)s->m_decay; } //----------------------------------------------------------------------------- // name: Shakers_cget_decay() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Shakers_cget_decay ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)s->m_decay; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_objects() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_objects ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT e = GET_NEXT_FLOAT(ARGS); s->controlChange( 11, e ); s->m_objects = e; RETURN->v_float = (t_CKFLOAT)s->m_objects; } //----------------------------------------------------------------------------- // name: Shakers_cget_objects() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Shakers_cget_objects ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)s->m_objects; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_freq ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); s->freq = GET_NEXT_FLOAT(ARGS); s->controlChange( __SK_ModWheel_, ftom(s->freq) ); RETURN->v_float = (t_CKFLOAT)s->freq; } //----------------------------------------------------------------------------- // name: Shakers_cget_freq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( Shakers_cget_freq ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT( SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)s->freq; } //----------------------------------------------------------------------------- // name: Shakers_ctrl_noteOn() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_noteOn ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); s->ck_noteOn( f ); } //----------------------------------------------------------------------------- // name: Shakers_ctrl_noteOff() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( Shakers_ctrl_noteOff ) { Shakers * s = (Shakers *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); s->noteOff( f ); } //----------------------------------------------------------------------------- // name: SubNoise_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( SubNoise_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, SubNoise_offset_data) = (t_CKUINT)new SubNoise( ); } //----------------------------------------------------------------------------- // name: SubNoise_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( SubNoise_dtor ) { delete (SubNoise *)OBJ_MEMBER_UINT(SELF, SubNoise_offset_data); OBJ_MEMBER_UINT(SELF, SubNoise_offset_data) = 0; } //----------------------------------------------------------------------------- // name: SubNoise_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( SubNoise_tick ) { SubNoise * p = (SubNoise *)OBJ_MEMBER_UINT(SELF, SubNoise_offset_data); *out = p->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: SubNoise_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( SubNoise_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: SubNoise_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( SubNoise_ctrl_rate ) { SubNoise * p = (SubNoise *)OBJ_MEMBER_UINT(SELF, SubNoise_offset_data); int i = GET_CK_INT(ARGS); p->setRate( i ); RETURN->v_int = (t_CKINT) (int)((SubNoise *)OBJ_MEMBER_UINT(SELF, SubNoise_offset_data))->subRate(); } //----------------------------------------------------------------------------- // name: SubNoise_cget_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CGET( SubNoise_cget_rate ) { RETURN->v_int = (t_CKINT) (int)((SubNoise *)OBJ_MEMBER_UINT(SELF, SubNoise_offset_data))->subRate(); } //----------------------------------------------------------------------------- // name: VoicForm_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( VoicForm_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = (t_CKUINT)new VoicForm(); } //----------------------------------------------------------------------------- // name: VoicForm_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( VoicForm_dtor ) { delete (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data) = 0; } //----------------------------------------------------------------------------- // name: VoicForm_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( VoicForm_tick ) { VoicForm * m = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); *out = m->tick(); return TRUE; } //----------------------------------------------------------------------------- // name: VoicForm_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( VoicForm_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_speak() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_speak ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); v->speak(); } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_quiet() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_quiet ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); v->quiet(); } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_phoneme() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_phoneme ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); const char * c = GET_CK_STRING(ARGS)->str.c_str(); v->setPhoneme( c ); RETURN->v_string = &(v->str_phoneme); } //----------------------------------------------------------------------------- // name: VoicForm_cget_phoneme() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_phoneme ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_string = &(v->str_phoneme); } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_voiced() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_voiced ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->setVoiced( f ); RETURN->v_float = (t_CKFLOAT)v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_cget_voiced() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_voiced ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_unVoiced() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_unVoiced ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->setUnVoiced( f ); //not sure if this should be multiplied RETURN->v_float = (t_CKFLOAT)v->noiseEnv->value; } //----------------------------------------------------------------------------- // name: VoicForm_cget_unVoiced() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_unVoiced ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)v->noiseEnv->value; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_voiceMix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_voiceMix ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->controlChange(__SK_Breath_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT)v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_cget_voiceMix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_voiceMix ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_selPhoneme() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_selPhoneme ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); int i = GET_CK_INT(ARGS); v->controlChange(__SK_FootControl_, i); RETURN->v_float = (t_CKFLOAT)v->m_phonemeNum; } //----------------------------------------------------------------------------- // name: VoicForm_cget_selPhoneme() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_selPhoneme ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)v->m_phonemeNum; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_vibratoFreq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_vibratoFreq ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->voiced->modulator->vibrato->setFrequency( f ); RETURN->v_float = (t_CKFLOAT)v->voiced->modulator->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: VoicForm_cget_vibratoFreq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_vibratoFreq ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT)v->voiced->modulator->vibrato->m_freq; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_vibratoGain() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_vibratoGain ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->controlChange(__SK_ModWheel_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) v->voiced->modulator->vibratoGain; } //----------------------------------------------------------------------------- // name: VoicForm_cget_vibratoGain() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_vibratoGain ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) v->voiced->modulator->vibratoGain; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_loudness() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_loudness ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->controlChange(__SK_AfterTouch_Cont_, f * 128.0 ); RETURN->v_float = (t_CKFLOAT) v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_cget_loudness() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_loudness ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) v->voiced->envelope->value; } //----------------------------------------------------------------------------- // name: VoicForm_ctrl_pitchSweepRate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( VoicForm_ctrl_pitchSweepRate ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); v->setPitchSweepRate( f ); RETURN->v_float = (t_CKFLOAT) v->voiced->m_freq; } //----------------------------------------------------------------------------- // name: VoicForm_cget_pitchSweepRate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( VoicForm_cget_pitchSweepRate ) { VoicForm * v = (VoicForm *)OBJ_MEMBER_UINT(SELF, Instrmnt_offset_data); RETURN->v_float = (t_CKFLOAT) v->voiced->m_freq; } // WvIn //----------------------------------------------------------------------------- // name: WvIn_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( WvIn_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, WvIn_offset_data) = (t_CKUINT)new WvIn; } //----------------------------------------------------------------------------- // name: WvIn_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( WvIn_dtor ) { delete (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); OBJ_MEMBER_UINT(SELF, WvIn_offset_data) = 0; } //----------------------------------------------------------------------------- // name: WvIn_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( WvIn_tick ) { WvIn * w = (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); *out = ( w->m_loaded ? (t_CKFLOAT)w->tick() / SHRT_MAX : (SAMPLE)0.0 ); return TRUE; } //----------------------------------------------------------------------------- // name: WvIn_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( WvIn_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: WvIn_ctrl_rate() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvIn_ctrl_rate ) { WvIn * w = (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); w->setRate( f ); RETURN->v_float = (t_CKFLOAT) w->rate; } //----------------------------------------------------------------------------- // name: WvIn_ctrl_path() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvIn_ctrl_path ) { WvIn * w = (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); const char * c = GET_CK_STRING(ARGS)->str.c_str(); try { w->openFile( c, FALSE, FALSE ); } catch( StkError & e ) { const char * s = e.getMessage(); // fprintf( stderr, "[chuck](via STK): WvIn cannot load file '%s'\n", c ); s = ""; } RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvIn_cget_rate() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WvIn_cget_rate ) { WvIn * w = (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); RETURN->v_float = (t_CKFLOAT) w->rate; } //----------------------------------------------------------------------------- // name: WvIn_cget_path() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WvIn_cget_path ) { WvIn * w = (WvIn *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); RETURN->v_string = &(w->str_filename); } // WaveLoop //----------------------------------------------------------------------------- // name: WaveLoop_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( WaveLoop_ctor ) { // initialize member object OBJ_MEMBER_UINT(SELF, WvIn_offset_data) = (t_CKUINT)new WaveLoop; } //----------------------------------------------------------------------------- // name: WaveLoop_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( WaveLoop_dtor ) { delete (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); OBJ_MEMBER_UINT(SELF, WvIn_offset_data) = 0; } //----------------------------------------------------------------------------- // name: WaveLoop_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( WaveLoop_tick ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); *out = ( w->m_loaded ? (t_CKFLOAT)w->tick() / SHRT_MAX : (SAMPLE)0.0 ); return TRUE; } //----------------------------------------------------------------------------- // name: WaveLoop_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( WaveLoop_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: WaveLoop_ctrl_freq() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WaveLoop_ctrl_freq ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); w->setFrequency( f ); RETURN->v_float = (t_CKFLOAT) w->m_freq; } //----------------------------------------------------------------------------- // name: WaveLoop_cget_freq() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WaveLoop_cget_freq ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); RETURN->v_float = (t_CKFLOAT) w->m_freq; } //----------------------------------------------------------------------------- // name: WaveLoop_ctrl_phase() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WaveLoop_ctrl_phase ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); float f = (float)GET_NEXT_FLOAT(ARGS); w->addPhase( f ); RETURN->v_float = (t_CKFLOAT) w->time / w->fileSize; } //----------------------------------------------------------------------------- // name: WaveLoop_cget_phase() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WaveLoop_cget_phase ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); RETURN->v_float = (t_CKFLOAT) w->time / w->fileSize; } //----------------------------------------------------------------------------- // name: WaveLoop_ctrl_phaseOffset() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WaveLoop_ctrl_phaseOffset ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); w->addPhaseOffset( f ); RETURN->v_float = (t_CKFLOAT) w->phaseOffset; } //----------------------------------------------------------------------------- // name: WaveLoop_cget_phaseOffset() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WaveLoop_cget_phaseOffset ) { WaveLoop * w = (WaveLoop *)OBJ_MEMBER_UINT(SELF, WvIn_offset_data); RETURN->v_float = (t_CKFLOAT) w->phaseOffset; } std::map g_wv; // WvOut //----------------------------------------------------------------------------- // name: WvOut_ctor() // desc: CTOR function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( WvOut_ctor ) { WvOut * yo = new WvOut; yo->autoPrefix.str = "chuck-session"; OBJ_MEMBER_UINT(SELF, WvOut_offset_data) = (t_CKUINT)yo; } //----------------------------------------------------------------------------- // name: WvOut_dtor() // desc: DTOR function ... //----------------------------------------------------------------------------- CK_DLL_DTOR( WvOut_dtor ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); w->closeFile(); std::map::iterator iter; iter = g_wv.find( w ); g_wv.erase( iter ); delete (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); OBJ_MEMBER_UINT(SELF, WvOut_offset_data) = 0; } //----------------------------------------------------------------------------- // name: WvOut_tick() // desc: TICK function ... //----------------------------------------------------------------------------- CK_DLL_TICK( WvOut_tick ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); if( w->start ) w->tick( in ); *out = in; // pass samples downstream return TRUE; } //----------------------------------------------------------------------------- // name: WvOut_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG( WvOut_pmsg ) { return TRUE; } // XXX chuck got mono, so we have one channel. fix later. //----------------------------------------------------------------------------- // name: WvOut_ctrl_matFilename() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_matFilename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); char buffer[1024]; // special if( strstr( filename, "special:auto" ) ) { time_t t; time(&t); strcpy( buffer, w->autoPrefix.str.c_str() ); strcat( buffer, "(" ); strncat( buffer, ctime(&t), 24 ); buffer[strlen(w->autoPrefix.str.c_str())+14] = 'h'; buffer[strlen(w->autoPrefix.str.c_str())+17] = 'm'; strcat( buffer, ").mat" ); filename = buffer; } w->openFile( filename, 1, WvOut::WVOUT_MAT, Stk::STK_SINT16 ); g_wv[w] = w; RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_sndFilename() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_sndFilename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); char buffer[1024]; // special if( strstr( filename, "special:auto" ) ) { time_t t; time(&t); strcpy( buffer, w->autoPrefix.str.c_str() ); strcat( buffer, "(" ); strncat( buffer, ctime(&t), 24 ); buffer[strlen(w->autoPrefix.str.c_str())+14] = 'h'; buffer[strlen(w->autoPrefix.str.c_str())+17] = 'm'; strcat( buffer, ").snd" ); filename = buffer; } w->openFile( filename, 1, WvOut::WVOUT_SND, Stk::STK_SINT16 ); g_wv[w] = w; RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_wavFilename() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_wavFilename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); char buffer[1024]; // special if( strstr( filename, "special:auto" ) ) { time_t t; time(&t); strcpy( buffer, w->autoPrefix.str.c_str() ); strcat( buffer, "(" ); strncat( buffer, ctime(&t), 24 ); buffer[strlen(w->autoPrefix.str.c_str())+14] = 'h'; buffer[strlen(w->autoPrefix.str.c_str())+17] = 'm'; strcat( buffer, ").wav" ); filename = buffer; } w->openFile( filename, 1, WvOut::WVOUT_WAV, Stk::STK_SINT16 ); g_wv[w] = w; RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_rawFilename() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_rawFilename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); char buffer[1024]; // special if( strstr( filename, "special:auto" ) ) { time_t t; time(&t); strcpy( buffer, w->autoPrefix.str.c_str() ); strcat( buffer, "(" ); strncat( buffer, ctime(&t), 24 ); buffer[strlen(w->autoPrefix.str.c_str())+14] = 'h'; buffer[strlen(w->autoPrefix.str.c_str())+17] = 'm'; strcat( buffer, ").raw" ); filename = buffer; } w->openFile( filename, 1, WvOut::WVOUT_RAW, Stk::STK_SINT16 ); g_wv[w] = w; RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_aifFilename() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_aifFilename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); char buffer[1024]; // special if( strstr( filename, "special:auto" ) ) { time_t t; time(&t); strcpy( buffer, w->autoPrefix.str.c_str() ); strcat( buffer, "(" ); strncat( buffer, ctime(&t), 24 ); buffer[strlen(w->autoPrefix.str.c_str())+14] = 'h'; buffer[strlen(w->autoPrefix.str.c_str())+17] = 'm'; strcat( buffer, ").aiff" ); filename = buffer; } w->openFile( filename, 1, WvOut::WVOUT_AIF, Stk::STK_SINT16 ); g_wv[w] = w; RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_cget_filename() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WvOut_cget_filename ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); RETURN->v_string = &(w->str_filename); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_closeFile() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_closeFile ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); w->closeFile(); std::map::iterator iter; iter = g_wv.find( w ); g_wv.erase( iter ); } //----------------------------------------------------------------------------- // name: WvOut_ctrl_record() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_record ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); t_CKINT i = GET_NEXT_INT(ARGS); w->start = i ? 1 : 0; RETURN->v_int = (t_CKINT) w->start; } //----------------------------------------------------------------------------- // name: WvOut_cget_record() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WvOut_cget_record ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); RETURN->v_int = (t_CKINT) w->start; } //----------------------------------------------------------------------------- // name: WvOut_ctrl_autoPrefix() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( WvOut_ctrl_autoPrefix ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); w->autoPrefix.str = GET_NEXT_STRING(ARGS)->str.c_str(); RETURN->v_string = &w->autoPrefix; } //----------------------------------------------------------------------------- // name: WvOut_cget_autoPrefix() // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CGET( WvOut_cget_autoPrefix ) { WvOut * w = (WvOut *)OBJ_MEMBER_UINT(SELF, WvOut_offset_data); RETURN->v_string = &w->autoPrefix; } //----------------------------------------------------------------------------- // BLT //----------------------------------------------------------------------------- CK_DLL_CTOR( BLT_ctor ) { /* do nothing here */ } CK_DLL_DTOR( BLT_dtor ) { /* do nothing here */ } CK_DLL_TICK( BLT_tick ) { fprintf( stderr, "BLT is virtual!\n" ); return TRUE; } CK_DLL_PMSG( BLT_pmsg ) { return TRUE; } CK_DLL_CTRL( BLT_ctrl_phase ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); blt->setPhase( f ); blt->m_phase = f; RETURN->v_float = f; } CK_DLL_CGET( BLT_cget_phase ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); RETURN->v_float = blt->getValuePhase(); } CK_DLL_CTRL( BLT_ctrl_freq ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); blt->setFrequency( f ); blt->m_freq = f; RETURN->v_float = f; } CK_DLL_CGET( BLT_cget_freq ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); RETURN->v_float = blt->getValueFreq(); } CK_DLL_CTRL( BLT_ctrl_harmonics ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); t_CKINT i = GET_CK_INT(ARGS); if( i < 0 ) i = -i; blt->setHarmonics( i ); blt->m_harmonics = i; RETURN->v_int = i; } CK_DLL_CGET( BLT_cget_harmonics ) { BLT * blt = (BLT *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); RETURN->v_int = blt->getValueHarmonics(); } //----------------------------------------------------------------------------- // Blit //----------------------------------------------------------------------------- CK_DLL_CTOR( Blit_ctor ) { Blit * blit = new Blit; OBJ_MEMBER_UINT(SELF, BLT_offset_data) = (t_CKUINT)blit; } CK_DLL_DTOR( Blit_dtor ) { delete (Blit *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); OBJ_MEMBER_UINT(SELF, BLT_offset_data) = 0; } CK_DLL_TICK( Blit_tick ) { Blit * blit = (Blit *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); *out = blit->tick(); return TRUE; } CK_DLL_PMSG( Blit_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // BlitSaw //----------------------------------------------------------------------------- CK_DLL_CTOR( BlitSaw_ctor ) { BlitSaw * blit = new BlitSaw; OBJ_MEMBER_UINT(SELF, BLT_offset_data) = (t_CKUINT)blit; } CK_DLL_DTOR( BlitSaw_dtor ) { delete (BlitSaw *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); OBJ_MEMBER_UINT(SELF, BLT_offset_data) = 0; } CK_DLL_TICK( BlitSaw_tick ) { BlitSaw * blit = (BlitSaw *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); *out = blit->tick(); return TRUE; } CK_DLL_PMSG( BlitSaw_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // BlitSquare //----------------------------------------------------------------------------- CK_DLL_CTOR( BlitSquare_ctor ) { BlitSquare * blit = new BlitSquare; OBJ_MEMBER_UINT(SELF, BLT_offset_data) = (t_CKUINT)blit; } CK_DLL_DTOR( BlitSquare_dtor ) { delete (BlitSquare *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); OBJ_MEMBER_UINT(SELF, BLT_offset_data) = 0; } CK_DLL_TICK( BlitSquare_tick ) { BlitSquare * blit = (BlitSquare *)OBJ_MEMBER_UINT(SELF, BLT_offset_data); *out = blit->tick(); return TRUE; } CK_DLL_PMSG( BlitSquare_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: JetTable // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( JetTabl_ctor ) { JetTabl * j = new JetTabl; OBJ_MEMBER_UINT(SELF, JetTabl_offset_data) = (t_CKUINT)j; } CK_DLL_DTOR( JetTabl_dtor ) { JetTabl * j = (JetTabl *)OBJ_MEMBER_UINT(SELF, JetTabl_offset_data); SAFE_DELETE(j); OBJ_MEMBER_UINT(SELF, JetTabl_offset_data) = 0; } CK_DLL_TICK( JetTabl_tick ) { JetTabl * j = (JetTabl *)OBJ_MEMBER_UINT(SELF, JetTabl_offset_data); *out = j->tick( in ); return TRUE; } CK_DLL_PMSG( JetTabl_pmsg ) { return TRUE; } //----------------------------------------------------------------------------- // name: Mesh2D ctor // desc: CGET function ... //----------------------------------------------------------------------------- CK_DLL_CTOR( Mesh2D_ctor ) { Mesh2D * m = new Mesh2D( 2,2 ); OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data) = (t_CKUINT)m; } CK_DLL_DTOR( Mesh2D_dtor ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); SAFE_DELETE(m); OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data) = 0; } CK_DLL_TICK( Mesh2D_tick ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); *out = m->tick( in ); return TRUE; } CK_DLL_PMSG( Mesh2D_pmsg ) { return TRUE; } CK_DLL_CTRL( Mesh2D_ctrl_nx ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); m->setNX( GET_NEXT_INT ( ARGS ) ); } CK_DLL_CTRL( Mesh2D_ctrl_ny ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); m->setNY( GET_NEXT_INT ( ARGS ) ); } CK_DLL_CGET( Mesh2D_cget_nx ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); RETURN->v_int = m->NX; } CK_DLL_CGET( Mesh2D_cget_ny ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); RETURN->v_int = m->NY; } CK_DLL_CTRL( Mesh2D_ctrl_input_position ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); t_CKFLOAT xpos = GET_NEXT_FLOAT(ARGS); t_CKFLOAT ypos = GET_NEXT_FLOAT(ARGS); m->setInputPosition(xpos,ypos); } CK_DLL_CTRL( Mesh2D_cget_input_position ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); RETURN->v_float = m->xInput / (m->NX - 1); } CK_DLL_CTRL( Mesh2D_ctrl_decay ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); t_CKFLOAT dec = GET_NEXT_FLOAT ( ARGS ); m->setDecay( dec ); RETURN->v_float = dec; } CK_DLL_CGET( Mesh2D_cget_decay ) { } CK_DLL_CTRL( Mesh2D_ctrl_note_on ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); t_CKFLOAT note = GET_NEXT_FLOAT(ARGS); t_CKFLOAT vel = GET_NEXT_FLOAT(ARGS); m->noteOn( note, vel ); } CK_DLL_CTRL( Mesh2D_ctrl_note_off ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); m->noteOff( GET_NEXT_FLOAT(ARGS) ); //need a version that takes a float } CK_DLL_CGET( Mesh2D_cget_energy ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); RETURN->v_float = m->energy(); } CK_DLL_CTRL ( Mesh2D_ctrl_control_change ) { Mesh2D * m = (Mesh2D *)OBJ_MEMBER_UINT(SELF, Mesh2D_offset_data); t_CKINT ctrl = GET_NEXT_INT(ARGS); t_CKFLOAT val = GET_NEXT_FLOAT(ARGS); m->controlChange( ctrl, val ); } //----------------------------------------------------------------------------- // name: ck_detach() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL stk_detach( t_CKUINT type, void * data ) { std::map::iterator iter; // log EM_log( CK_LOG_INFO, "(via STK): detaching file handles..." ); for( iter = g_wv.begin(); iter != g_wv.end(); iter++ ) { (*iter).second->closeFile(); } // TODO: release the WvOut g_wv.clear(); return TRUE; } chuck-1.2.0.8.dfsg/src/ugen_stk.h0000644000175000017500000051714310600421721015130 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_stk.h // desc: ChucK import for Synthesis ToolKit (STK) // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // Ari Lazier (alazier@cs.princeton.edu) // Philip L. Davidson (philipd@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __UGEN_STK_H__ #define __UGEN_STK_H__ #include "chuck_dl.h" // query DLL_QUERY stk_query( Chuck_DL_Query * QUERY ); t_CKBOOL stk_detach( t_CKUINT type, void * data ); // this determines STK float type and de-denormal method #if 1 #define MY_FLOAT double #define CK_STK_DDN CK_DDN_DOUBLE #else #define MY_FLOAT float #define CK_STK_DDN CK_DDN_SINGLE #endif /***************************************************/ /*! \class Stk \brief STK base class Nearly all STK classes inherit from this class. The global sample rate and rawwave path variables can be queried and modified via Stk. In addition, this class provides error handling and byte-swapping functions. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__STK_H) #define __STK_H #include #include // Most data in STK is passed and calculated with the // following user-definable floating-point type. You // can change this to "float" if you prefer or perhaps // a "long double" in the future. //XXX sample is already defined in chuck_def.h!!! #if !defined(SAMPLE) typedef SAMPLE MY_FLOAT; #endif // The "MY_FLOAT" type will be deprecated in STK // versions higher than 4.1.2 and replaced with the variable // "StkFloat". //typedef double StkFloat; //#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) // #pragma deprecated(MY_FLOAT) //#else // typedef StkFloat MY_FLOAT __attribute__ ((deprecated)); //#endif //! STK error handling class. /*! This is a fairly abstract exception handling class. There could be sub-classes to take care of more specific error conditions ... or not. */ class StkError { public: enum TYPE { WARNING, DEBUG_WARNING, FUNCTION_ARGUMENT, FILE_NOT_FOUND, FILE_UNKNOWN_FORMAT, FILE_ERROR, PROCESS_THREAD, PROCESS_SOCKET, PROCESS_SOCKET_IPADDR, AUDIO_SYSTEM, MIDI_SYSTEM, UNSPECIFIED }; public: // SWAP formerly protected char message[256]; TYPE type; public: //! The constructor. StkError(const char *p, TYPE tipe = StkError::UNSPECIFIED); //! The destructor. virtual ~StkError(void); //! Prints "thrown" error message to stdout. virtual void printMessage(void); //! Returns the "thrown" error message TYPE. virtual const TYPE& getType(void) { return type; } //! Returns the "thrown" error message string. virtual const char *getMessage(void) const { return message; } }; class Stk { public: typedef unsigned long STK_FORMAT; static const STK_FORMAT STK_SINT8; /*!< -128 to +127 */ static const STK_FORMAT STK_SINT16; /*!< -32768 to +32767 */ static const STK_FORMAT STK_SINT32; /*!< -2147483648 to +2147483647. */ static const STK_FORMAT MY_FLOAT32; /*!< Normalized between plus/minus 1.0. */ static const STK_FORMAT MY_FLOAT64; /*!< Normalized between plus/minus 1.0. */ //! Static method which returns the current STK sample rate. static MY_FLOAT sampleRate(void); //! Static method which sets the STK sample rate. /*! The sample rate set using this method is queried by all STK classes which depend on its value. It is initialized to the default SRATE set in Stk.h. Many STK classes use the sample rate during instantiation. Therefore, if you wish to use a rate which is different from the default rate, it is imperative that it be set \e BEFORE STK objects are instantiated. */ static void setSampleRate(MY_FLOAT newRate); //! Static method which returns the current rawwave path. static std::string rawwavePath(void); //! Static method which sets the STK rawwave path. static void setRawwavePath(std::string newPath); //! Static method which byte-swaps a 16-bit data type. static void swap16(unsigned char *ptr); //! Static method which byte-swaps a 32-bit data type. static void swap32(unsigned char *ptr); //! Static method which byte-swaps a 64-bit data type. static void swap64(unsigned char *ptr); //! Static cross-platform method to sleep for a number of milliseconds. static void sleep(unsigned long milliseconds); public: // SWAP formerly private static MY_FLOAT srate; static std::string rawwavepath; public: // SWAP formerly protected //! Default constructor. Stk(void); //! Class destructor. virtual ~Stk(void); //! Function for error reporting and handling. static void handleError( const char *message, StkError::TYPE type ); }; // Here are a few other useful typedefs. typedef signed short SINT16; typedef signed int SINT32; typedef float FLOAT32; typedef double FLOAT64; // Boolean values #ifndef TRUE #define FALSE 0 #define TRUE 1 #endif // The default sampling rate. #define SRATE (MY_FLOAT) 44100.0 // The default real-time audio input and output buffer size. If // clicks are occuring in the input and/or output sound stream, a // larger buffer size may help. Larger buffer sizes, however, produce // more latency. #define RT_BUFFER_SIZE 512 // The default rawwave path value is set with the preprocessor // definition RAWWAVE_PATH. This can be specified as an argument to // the configure script, in an integrated development environment, or // below. The global STK rawwave path variable can be dynamically set // with the Stk::setRawwavePath() function. This value is // concatenated to the beginning of all references to rawwave files in // the various STK core classes (ex. Clarinet.cpp). If you wish to // move the rawwaves directory to a different location in your file // system, you will need to set this path definition appropriately. #if !defined(RAWWAVE_PATH) #define RAWWAVE_PATH "../../rawwaves/" #endif //#define PI (MY_FLOAT) 3.14159265359 //#define TWO_PI (MY_FLOAT) (2 * PI) #define ONE_OVER_128 (MY_FLOAT) 0.0078125 #if defined(__WINDOWS_PTHREAD__) #define __OS_WINDOWS_CYGWIN__ #define __STK_REALTIME__ #elif defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) #define __OS_WINDOWS__ #define __STK_REALTIME__ #elif defined(__LINUX_OSS__) || defined(__LINUX_ALSA__) || defined(__LINUX_JACK__) #define __OS_LINUX__ #define __STK_REALTIME__ #elif defined(__IRIX_AL__) #define __OS_IRIX__ #define __STK_REALTIME__ #elif defined(__MACOSX_CORE__) #define __OS_MACOSX__ #define __STK_REALTIME__ #endif //#define _STK_DEBUG_ #endif /***************************************************/ /*! \class Envelope \brief STK envelope base class. This class implements a simple envelope generator which is capable of ramping to a target value by a specified \e rate. It also responds to simple \e keyOn and \e keyOff messages, ramping to 1.0 on keyOn and to 0.0 on keyOff. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__ENVELOPE_H) #define __ENVELOPE_H class Envelope : public Stk { public: //! Default constructor. Envelope(void); //! Class destructor. virtual ~Envelope(void); //! Set target = 1. virtual void keyOn(void); //! Set target = 0. virtual void keyOff(void); //! Set the \e rate. void setRate(MY_FLOAT aRate); //! Set the \e rate based on a time duration. void setTime(MY_FLOAT aTime); //! Set the target value. virtual void setTarget(MY_FLOAT aTarget); //! Set current and target values to \e aValue. virtual void setValue(MY_FLOAT aValue); //! Return the current envelope \e state (0 = at target, 1 otherwise). virtual int getState(void) const; //! Return one envelope output value. virtual MY_FLOAT tick(void); //! Return \e vectorSize envelope outputs in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Return the last computed output value. MY_FLOAT lastOut(void) const; public: MY_FLOAT value; MY_FLOAT target; MY_FLOAT rate; MY_FLOAT m_target; // chuck MY_FLOAT m_time; // chuck int state; }; #endif /***************************************************/ /*! \class ADSR \brief STK ADSR envelope class. This Envelope subclass implements a traditional ADSR (Attack, Decay, Sustain, Release) envelope. It responds to simple keyOn and keyOff messages, keeping track of its state. The \e state = ADSR::DONE after the envelope value reaches 0.0 in the ADSR::RELEASE state. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__ADSR_H) #define __ADSR_H class ADSR : public Envelope { public: //! Envelope states. enum { ATTACK, DECAY, SUSTAIN, RELEASE, DONE }; //! Default constructor. ADSR(void); //! Class destructor. virtual ~ADSR(void); //! Set target = 1, state = \e ADSR::ATTACK. virtual void keyOn(void); //! Set target = 0, state = \e ADSR::RELEASE. virtual void keyOff(void); //! Set the attack rate. void setAttackRate(MY_FLOAT aRate); //! Set the decay rate. void setDecayRate(MY_FLOAT aRate); //! Set the sustain level. void setSustainLevel(MY_FLOAT aLevel); //! Set the release rate. void setReleaseRate(MY_FLOAT aRate); //! Set the attack rate based on a time duration. void setAttackTime(MY_FLOAT aTime); //! Set the decay rate based on a time duration. void setDecayTime(MY_FLOAT aTime); //! Set the release rate based on a time duration. void setReleaseTime(MY_FLOAT aTime); //! Set sustain level and attack, decay, and release state rates based on time durations. void setAllTimes(MY_FLOAT aTime, MY_FLOAT dTime, MY_FLOAT sLevel, MY_FLOAT rTime); //! Set the target value. void setTarget(MY_FLOAT aTarget); //! Return the current envelope \e state (ATTACK, DECAY, SUSTAIN, RELEASE, DONE). int getState(void) const; //! Set to state = ADSR::SUSTAIN with current and target values of \e aValue. void setValue(MY_FLOAT aValue); //! Return one envelope output value. MY_FLOAT tick(void); //! Return \e vectorSize envelope outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); // chuck MY_FLOAT getAttackTime(); MY_FLOAT getDecayTime(); MY_FLOAT getReleaseTime(); public: MY_FLOAT attackRate; MY_FLOAT decayRate; MY_FLOAT sustainLevel; MY_FLOAT releaseRate; // chuck MY_FLOAT m_decayTime; MY_FLOAT m_releaseTime; }; #endif /***************************************************/ /*! \class Instrmnt \brief STK instrument abstract base class. This class provides a common interface for all STK instruments. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__INSTRMNT_H) #define __INSTRMNT_H #include class Instrmnt : public Stk { public: //! Default constructor. Instrmnt(); //! Class destructor. virtual ~Instrmnt(); //! Start a note with the given frequency and amplitude. virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude) = 0; //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude) = 0; //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the last left output value. MY_FLOAT lastOutLeft() const; //! Return the last right output value. MY_FLOAT lastOutRight() const; //! Compute one output sample. virtual MY_FLOAT tick() = 0; //! Computer \e vectorSize outputs and return them in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // chuck t_CKFLOAT m_frequency; MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class Filter (renamed to FilterStk) \brief STK filter class. This class implements a generic structure which can be used to create a wide range of filters. It can function independently or be subclassed to provide more specific controls based on a particular filter type. In particular, this class implements the standard difference equation: a[0]*y[n] = b[0]*x[n] + ... + b[nb]*x[n-nb] - a[1]*y[n-1] - ... - a[na]*y[n-na] If a[0] is not equal to 1, the filter coeffcients are normalized by a[0]. The \e gain parameter is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. This structure results in one extra multiply per computed sample, but allows easy control of the overall filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__FILTER_H) #define __FILTER_H class FilterStk : public Stk { public: //! Default constructor creates a zero-order pass-through "filter". FilterStk(void); //! Overloaded constructor which takes filter coefficients. /*! An StkError can be thrown if either \e nb or \e na is less than one, or if the a[0] coefficient is equal to zero. */ FilterStk(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients); //! Class destructor. virtual ~FilterStk(void); //! Clears all internal states of the filter. void clear(void); //! Set filter coefficients. /*! An StkError can be thrown if either \e nb or \e na is less than one, or if the a[0] coefficient is equal to zero. If a[0] is not equal to 1, the filter coeffcients are normalized by a[0]. */ void setCoefficients(int nb, MY_FLOAT *bCoefficients, int na, MY_FLOAT *aCoefficients); //! Set numerator coefficients. /*! An StkError can be thrown if \e nb is less than one. Any previously set denominator coefficients are left unaffected. Note that the default constructor sets the single denominator coefficient a[0] to 1.0. */ void setNumerator(int nb, MY_FLOAT *bCoefficients); //! Set denominator coefficients. /*! An StkError can be thrown if \e na is less than one or if the a[0] coefficient is equal to zero. Previously set numerator coefficients are unaffected unless a[0] is not equal to 1, in which case all coeffcients are normalized by a[0]. Note that the default constructor sets the single numerator coefficient b[0] to 1.0. */ void setDenominator(int na, MY_FLOAT *aCoefficients); //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ virtual void setGain(MY_FLOAT theGain); //! Return the current filter gain. virtual MY_FLOAT getGain(void) const; //! Return the last computed output value. virtual MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. virtual MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: MY_FLOAT gain; int nB; int nA; MY_FLOAT *b; MY_FLOAT *a; MY_FLOAT *outputs; MY_FLOAT *inputs; }; #endif /***************************************************/ /*! \class Delay \brief STK non-interpolating delay line class. This protected Filter subclass implements a non-interpolating digital delay-line. A fixed maximum length of 4095 and a delay of zero is set using the default constructor. Alternatively, the delay and maximum length can be set during instantiation with an overloaded constructor. A non-interpolating delay line is typically used in fixed delay-length applications, such as for reverberation. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__DELAY_H) #define __DELAY_H class Delay : public FilterStk { public: //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. Delay(); //! Overloaded constructor which specifies the current and maximum delay-line lengths. Delay(long theDelay, long maxDelay); //! Class destructor. virtual ~Delay(); //! Clears the internal state of the delay line. void clear(); //! Set the delay-line length. /*! The valid range for \e theDelay is from 0 to the maximum delay-line length. */ void setDelay(long theDelay); void set( long delay, long max ); //! Return the current delay-line length. MY_FLOAT getDelay(void) const; //! Calculate and return the signal energy in the delay-line. MY_FLOAT energy(void) const; //! Return the value at \e tapDelay samples from the delay-line input. /*! The tap point is determined modulo the delay-line length and is relative to the last input value (i.e., a tapDelay of zero returns the last input value). */ MY_FLOAT contentsAt(unsigned long tapDelay) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Return the value which will be output by the next call to tick(). /*! This method is valid only for delay settings greater than zero! */ virtual MY_FLOAT nextOut(void) const; //! Input one sample to the delay-line and return one output. virtual MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the delay-line and return an equal number of outputs in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: long inPoint; long outPoint; long length; MY_FLOAT delay; }; #endif /***************************************************/ /*! \class DelayL \brief STK linear interpolating delay line class. This Delay subclass implements a fractional- length digital delay-line using first-order linear interpolation. A fixed maximum length of 4095 and a delay of zero is set using the default constructor. Alternatively, the delay and maximum length can be set during instantiation with an overloaded constructor. Linear interpolation is an efficient technique for achieving fractional delay lengths, though it does introduce high-frequency signal attenuation to varying degrees depending on the fractional delay setting. The use of higher order Lagrange interpolators can typically improve (minimize) this attenuation characteristic. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__DELAYL_H) #define __DELAYL_H class DelayL : public Delay { public: //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. DelayL(); //! Overloaded constructor which specifies the current and maximum delay-line lengths. DelayL(MY_FLOAT theDelay, long maxDelay); //! Class destructor. ~DelayL(); //! Set the delay-line length. /*! The valid range for \e theDelay is from 0 to the maximum delay-line length. */ void setDelay(MY_FLOAT theDelay); void set( MY_FLOAT delay, long max ); //! Return the value which will be output by the next call to tick(). /*! This method is valid only for delay settings greater than zero! */ MY_FLOAT nextOut(void); //! Input one sample to the delay-line and return one output. MY_FLOAT tick(MY_FLOAT sample); public: // SWAP formerly protected MY_FLOAT alpha; MY_FLOAT omAlpha; MY_FLOAT nextOutput; bool doNextOut; }; #endif /***************************************************/ /*! \class BowTabl \brief STK bowed string table class. This class implements a simple bowed string non-linear function, as described by Smith (1986). by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BOWTABL_H) #define __BOWTABL_H class BowTabl : public Stk { public: //! Default constructor. BowTabl(); //! Class destructor. ~BowTabl(); //! Set the table offset value. /*! The table offset is a bias which controls the symmetry of the friction. If you want the friction to vary with direction, use a non-zero value for the offset. The default value is zero. */ void setOffset(MY_FLOAT aValue); //! Set the table slope value. /*! The table slope controls the width of the friction pulse, which is related to bow force. */ void setSlope(MY_FLOAT aValue); //! Return the last output value. MY_FLOAT lastOut(void) const; //! Return the function value for \e input. /*! The function input represents differential string-to-bow velocity. */ MY_FLOAT tick(const MY_FLOAT input); //! Take \e vectorSize inputs and return the corresponding function values in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected MY_FLOAT offSet; MY_FLOAT slope; MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class BiQuad \brief STK biquad (two-pole, two-zero) filter class. This protected Filter subclass implements a two-pole, two-zero digital filter. A method is provided for creating a resonance in the frequency response while maintaining a constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BIQUAD_H) #define __BIQUAD_H class BiQuad : public FilterStk { public: //! Default constructor creates a second-order pass-through filter. BiQuad(); //! Class destructor. virtual ~BiQuad(); //! Clears all internal states of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the b[1] coefficient value. void setB1(MY_FLOAT b1); //! Set the b[2] coefficient value. void setB2(MY_FLOAT b2); //! Set the a[1] coefficient value. void setA1(MY_FLOAT a1); //! Set the a[2] coefficient value. void setA2(MY_FLOAT a2); //! Sets the filter coefficients for a resonance at \e frequency (in Hz). /*! This method determines the filter coefficients corresponding to two complex-conjugate poles with the given \e frequency (in Hz) and \e radius from the z-plane origin. If \e normalize is true, the filter zeros are placed at z = 1, z = -1, and the coefficients are then normalized to produce a constant unity peak gain (independent of the filter \e gain parameter). The resulting filter frequency response has a resonance at the given \e frequency. The closer the poles are to the unit-circle (\e radius close to one), the narrower the resulting resonance width. */ void setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize = FALSE); //! Set the filter coefficients for a notch at \e frequency (in Hz). /*! This method determines the filter coefficients corresponding to two complex-conjugate zeros with the given \e frequency (in Hz) and \e radius from the z-plane origin. No filter normalization is attempted. */ void setNotch(MY_FLOAT frequency, MY_FLOAT radius); //! Sets the filter zeroes for equal resonance gain. /*! When using the filter as a resonator, zeroes places at z = 1, z = -1 will result in a constant gain at resonance of 1 / (1 - R), where R is the pole radius setting. */ void setEqualGainZeroes(); //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class BandedWG \brief Banded waveguide modeling class. This class uses banded waveguide techniques to model a variety of sounds, including bowed bars, glasses, and bowls. For more information, see Essl, G. and Cook, P. "Banded Waveguides: Towards Physical Modelling of Bar Percussion Instruments", Proceedings of the 1999 International Computer Music Conference. Control Change Numbers: - Bow Pressure = 2 - Bow Motion = 4 - Strike Position = 8 (not implemented) - Vibrato Frequency = 11 - Gain = 1 - Bow Velocity = 128 - Set Striking = 64 - Instrument Presets = 16 - Uniform Bar = 0 - Tuned Bar = 1 - Glass Harmonica = 2 - Tibetan Bowl = 3 by Georg Essl, 1999 - 2002. Modified for Stk 4.0 by Gary Scavone. */ /***************************************************/ #if !defined(__BANDEDWG_H) #define __BANDEDWG_H #define MAX_BANDED_MODES 20 class BandedWG : public Instrmnt { public: //! Class constructor. BandedWG(); //! Class destructor. ~BandedWG(); //! Reset and clear all internal state. void clear(); //! Set strike position (0.0 - 1.0). void setStrikePosition(MY_FLOAT position); //! Select a preset. void setPreset(int preset); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Apply bow velocity/pressure to instrument with given amplitude and rate of increase. void startBowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease bow velocity/breath pressure with given rate of decrease. void stopBowing(MY_FLOAT rate); //! Pluck the instrument with given amplitude. void pluck(MY_FLOAT amp); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT amplitude) { noteOn ( freakency, amplitude ); } void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected //chuck t_CKFLOAT m_rate; t_CKINT m_preset; t_CKFLOAT m_bowPressure; t_CKFLOAT m_bowMotion; t_CKFLOAT m_modesGain; t_CKFLOAT m_strikePosition; bool doPluck; bool trackVelocity; int nModes; int presetModes; BowTabl *bowTabl; ADSR *adsr; BiQuad *bandpass; DelayL *delay; MY_FLOAT maxVelocity; MY_FLOAT modes[MAX_BANDED_MODES]; MY_FLOAT freakency; MY_FLOAT baseGain; MY_FLOAT gains[MAX_BANDED_MODES]; MY_FLOAT basegains[MAX_BANDED_MODES]; MY_FLOAT excitation[MAX_BANDED_MODES]; MY_FLOAT integrationConstant; MY_FLOAT velocityInput; MY_FLOAT bowVelocity; MY_FLOAT bowTarget; MY_FLOAT bowPosition; MY_FLOAT strikeAmp; int strikePosition; }; #endif /***************************************************/ /*! \class WvIn \brief STK audio data input base class. This class provides input support for various audio file formats. It also serves as a base class for "realtime" streaming subclasses. WvIn loads the contents of an audio file for subsequent output. Linear interpolation is used for fractional "read rates". WvIn supports multi-channel data in interleaved format. It is important to distinguish the tick() methods, which return samples produced by averaging across sample frames, from the tickFrame() methods, which return pointers to multi-channel sample frames. For single-channel data, these methods return equivalent values. Small files are completely read into local memory during instantiation. Large files are read incrementally from disk. The file size threshold and the increment size values are defined in WvIn.h. WvIn currently supports WAV, AIFF, SND (AU), MAT-file (Matlab), and STK RAW file formats. Signed integer (8-, 16-, and 32-bit) and floating- point (32- and 64-bit) data types are supported. Uncompressed data types are not supported. If using MAT-files, data should be saved in an array with each data channel filling a matrix row. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__WVIN_H) #define __WVIN_H // Files larger than CHUNK_THRESHOLD will be copied into memory // in CHUNK_SIZE increments, rather than completely loaded into // a buffer at once. #define CHUNK_THRESHOLD 5000000 // 5 Mb #define CHUNK_SIZE 1024 // sample frames #include class WvIn : public Stk { public: //! Default constructor. WvIn(); //! Overloaded constructor for file input. /*! An StkError will be thrown if the file is not found, its format is unknown, or a read error occurs. */ WvIn( const char *fileName, bool raw = FALSE, bool doNormalize = TRUE, bool generate=true ); //! Class destructor. virtual ~WvIn(); //! Open the specified file and load its data. /*! An StkError will be thrown if the file is not found, its format is unknown, or a read error occurs. */ virtual void openFile( const char *fileName, bool raw = FALSE, bool doNormalize = TRUE, bool generate = true ); //! If a file is open, close it. void closeFile(void); //! Clear outputs and reset time (file pointer) to zero. void reset(void); //! Normalize data to a maximum of +-1.0. /*! For large, incrementally loaded files with integer data types, normalization is computed relative to the data type maximum. No normalization is performed for incrementally loaded files with floating-point data types. */ void normalize(void); //! Normalize data to a maximum of \e +-peak. /*! For large, incrementally loaded files with integer data types, normalization is computed relative to the data type maximum (\e peak/maximum). For incrementally loaded files with floating- point data types, direct scaling by \e peak is performed. */ void normalize(MY_FLOAT peak); //! Return the file size in sample frames. unsigned long getSize(void) const; //! Return the number of audio channels in the file. unsigned int getChannels(void) const; //! Return the input file sample rate in Hz (not the data read rate). /*! WAV, SND, and AIF formatted files specify a sample rate in their headers. STK RAW files have a sample rate of 22050 Hz by definition. MAT-files are assumed to have a rate of 44100 Hz. */ MY_FLOAT getFileRate(void) const; //! Query whether reading is complete. bool isFinished(void) const; //! Set the data read rate in samples. The rate can be negative. /*! If the rate value is negative, the data is read in reverse order. */ void setRate(MY_FLOAT aRate); //! Increment the read pointer by \e aTime samples. virtual void addTime(MY_FLOAT aTime); //! Turn linear interpolation on/off. /*! Interpolation is automatically off when the read rate is an integer value. If interpolation is turned off for a fractional rate, the time index is truncated to an integer value. */ void setInterpolate(bool doInterpolate); //! Return the average across the last output sample frame. virtual MY_FLOAT lastOut(void) const; //! Read out the average across one sample frame of data. /*! An StkError will be thrown if a file is read incrementally and a read error occurs. */ virtual MY_FLOAT tick(void); //! Read out vectorSize averaged sample frames of data in \e vector. /*! An StkError will be thrown if a file is read incrementally and a read error occurs. */ virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Return a pointer to the last output sample frame. virtual const MY_FLOAT *lastFrame(void) const; //! Return a pointer to the next sample frame of data. /*! An StkError will be thrown if a file is read incrementally and a read error occurs. */ virtual const MY_FLOAT *tickFrame(void); //! Read out sample \e frames of data to \e frameVector. /*! An StkError will be thrown if a file is read incrementally and a read error occurs. */ virtual MY_FLOAT *tickFrame(MY_FLOAT *frameVector, unsigned int frames); public: // SWAP formerly protected // Initialize class variables. void init( void ); // Read file data. virtual void readData(unsigned long index); // Get STK RAW file information. bool getRawInfo( const char *fileName ); // Get WAV file header information. bool getWavInfo( const char *fileName ); // Get SND (AU) file header information. bool getSndInfo( const char *fileName ); // Get AIFF file header information. bool getAifInfo( const char *fileName ); // Get MAT-file header information. bool getMatInfo( const char *fileName ); char msg[256]; // char m_filename[256]; // chuck data Chuck_String str_filename; // chuck data FILE *fd; MY_FLOAT *data; MY_FLOAT *lastOutput; bool chunking; bool finished; bool interpolate; bool byteswap; unsigned long fileSize; unsigned long bufferSize; unsigned long dataOffset; unsigned int channels; long chunkPointer; STK_FORMAT dataType; MY_FLOAT fileRate; MY_FLOAT gain; MY_FLOAT time; MY_FLOAT rate; public: bool m_loaded; }; #endif // defined(__WVIN_H) /***************************************************/ /*! \class WaveLoop \brief STK waveform oscillator class. This class inherits from WvIn and provides audio file looping functionality. WaveLoop supports multi-channel data in interleaved format. It is important to distinguish the tick() methods, which return samples produced by averaging across sample frames, from the tickFrame() methods, which return pointers to multi-channel sample frames. For single-channel data, these methods return equivalent values. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__WAVELOOP_H) #define __WAVELOOP_H #include class WaveLoop : public WvIn { public: WaveLoop( ); //! Class constructor. WaveLoop( const char *fileName, bool raw = FALSE, bool generate = true ); virtual void openFile( const char * fileName, bool raw = FALSE, bool n = TRUE ); //! Class destructor. virtual ~WaveLoop(); //! Set the data interpolation rate based on a looping frequency. /*! This function determines the interpolation rate based on the file size and the current Stk::sampleRate. The \e aFrequency value corresponds to file cycles per second. The frequency can be negative, in which case the loop is read in reverse order. */ void setFrequency(MY_FLOAT aFrequency); //! Increment the read pointer by \e aTime samples, modulo file size. void addTime(MY_FLOAT aTime); //! Increment current read pointer by \e anAngle, relative to a looping frequency. /*! This function increments the read pointer based on the file size and the current Stk::sampleRate. The \e anAngle value is a multiple of file size. */ void addPhase(MY_FLOAT anAngle); //! Add a phase offset to the current read pointer. /*! This function determines a time offset based on the file size and the current Stk::sampleRate. The \e anAngle value is a multiple of file size. */ void addPhaseOffset(MY_FLOAT anAngle); //! Return a pointer to the next sample frame of data. const MY_FLOAT *tickFrame(void); public: // Read file data. void readData(unsigned long index); MY_FLOAT phaseOffset; MY_FLOAT m_freq; // chuck data; }; #endif // defined(__WAVELOOP_H) /***************************************************/ /*! \class TwoZero \brief STK two-zero filter class. This protected Filter subclass implements a two-zero digital filter. A method is provided for creating a "notch" in the frequency response while maintaining a constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__TWOZERO_H) #define __TWOZERO_H class TwoZero : public FilterStk // formerly protected Filter { public: //! Default constructor creates a second-order pass-through filter. TwoZero(); //! Class destructor. ~TwoZero(); //! Clears the internal states of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the b[1] coefficient value. void setB1(MY_FLOAT b1); //! Set the b[2] coefficient value. void setB2(MY_FLOAT b2); //! Sets the filter coefficients for a "notch" at \e frequency (in Hz). /*! This method determines the filter coefficients corresponding to two complex-conjugate zeros with the given \e frequency (in Hz) and \e radius from the z-plane origin. The coefficients are then normalized to produce a maximum filter gain of one (independent of the filter \e gain parameter). The resulting filter frequency response has a "notch" or anti-resonance at the given \e frequency. The closer the zeros are to the unit-circle (\e radius close to or equal to one), the narrower the resulting notch width. */ void setNotch(MY_FLOAT frequency, MY_FLOAT radius); void ck_setNotchFreq ( MY_FLOAT freq ) { m_notchFreq = freq; setNotch (m_notchFreq, m_notchRad); } void ck_setNotchRad ( MY_FLOAT rad ) { m_notchRad = rad; setNotch (m_notchFreq, m_notchRad); } //chuck helper functions MY_FLOAT m_notchFreq; MY_FLOAT m_notchRad; //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class FM \brief STK abstract FM synthesis base class. This class controls an arbitrary number of waves and envelopes, determined via a constructor argument. Control Change Numbers: - Control One = 2 - Control Two = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__FM_H) #define __FM_H class FM : public Instrmnt { public: //! Class constructor, taking the number of wave/envelope operators to control. FM( int operators = 4 ); //! Class destructor. virtual ~FM(); //! Reset and clear all wave and envelope states. void clear(); //! Load the rawwave filenames in waves. void loadWaves(const char **filenames); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Set the frequency ratio for the specified wave. void setRatio(int waveIndex, MY_FLOAT ratio); //! Set the gain for the specified wave. void setGain(int waveIndex, MY_FLOAT gain); //! Set the modulation speed in Hz. void setModulationSpeed(MY_FLOAT mSpeed); //! Set the modulation depth. void setModulationDepth(MY_FLOAT mDepth); //! Set the value of control1. void setControl1(MY_FLOAT cVal); //! Set the value of control1. void setControl2(MY_FLOAT cVal); //! Start envelopes toward "on" targets. void keyOn(); //! Start envelopes toward "off" targets. void keyOff(); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Pure virtual function ... must be defined in subclasses. virtual MY_FLOAT tick() = 0; //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected ADSR **adsr; WaveLoop **waves; WaveLoop *vibrato; TwoZero *twozero; int nOperators; MY_FLOAT baseFrequency; MY_FLOAT *ratios; MY_FLOAT *gains; MY_FLOAT modDepth; MY_FLOAT control1; MY_FLOAT control2; MY_FLOAT __FM_gains[100]; MY_FLOAT __FM_susLevels[16]; MY_FLOAT __FM_attTimes[32]; }; #endif /***************************************************/ /*! \class BeeThree \brief STK Hammond-oid organ FM synthesis instrument. This class implements a simple 4 operator topology, also referred to as algorithm 8 of the TX81Z. \code Algorithm 8 is : 1 --. 2 -\| +-> Out 3 -/| 4 -- \endcode Control Change Numbers: - Operator 4 (feedback) Gain = 2 - Operator 3 Gain = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BEETHREE_H) #define __BEETHREE_H class BeeThree : public FM { public: //! Class constructor. BeeThree(); //! Class destructor. ~BeeThree(); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn( MY_FLOAT amplitude) { noteOn( baseFrequency, amplitude ); } //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class JetTabl \brief STK jet table class. This class implements a flue jet non-linear function, computed by a polynomial calculation. Contrary to the name, this is not a "table". Consult Fletcher and Rossing, Karjalainen, Cook, and others for more information. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__JETTABL_H) #define __JETTABL_H class JetTabl : public Stk { public: //! Default constructor. JetTabl(); //! Class destructor. ~JetTabl(); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the function value for \e input. MY_FLOAT tick(MY_FLOAT input); //! Take \e vectorSize inputs and return the corresponding function values in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class PoleZero \brief STK one-pole, one-zero filter class. This protected Filter subclass implements a one-pole, one-zero digital filter. A method is provided for creating an allpass filter with a given coefficient. Another method is provided to create a DC blocking filter. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__POLEZERO_H) #define __POLEZERO_H class PoleZero : public FilterStk // formerly protected Filter { public: //! Default constructor creates a first-order pass-through filter. PoleZero(); //! Class destructor. ~PoleZero(); //! Clears the internal states of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the b[1] coefficient value. void setB1(MY_FLOAT b1); //! Set the a[1] coefficient value. void setA1(MY_FLOAT a1); //! Set the filter for allpass behavior using \e coefficient. /*! This method uses \e coefficient to create an allpass filter, which has unity gain at all frequencies. Note that the \e coefficient magnitude must be less than one to maintain stability. */ void setAllpass(MY_FLOAT coefficient); //! Create a DC blocking filter with the given pole position in the z-plane. /*! This method sets the given pole position, together with a zero at z=1, to create a DC blocking filter. \e thePole should be close to one to minimize low-frequency attenuation. */ void setBlockZero(MY_FLOAT thePole = 0.99); //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class Noise \brief STK noise generator. Generic random number generation using the C rand() function. The quality of the rand() function varies from one OS to another. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__NOISE_H) #define __NOISE_H class Noise : public Stk { public: //! Default constructor which seeds the random number generator with the system time. Noise(); //! Constructor which seeds the random number generator with a given seed. /*! If the seed value is zero, the random number generator is seeded with the system time. */ Noise( unsigned int seed ); //! Class destructor. virtual ~Noise(); //! Seed the random number generator with a specific seed value. /*! If no seed is provided or the seed value is zero, the random number generator is seeded with the current system time. */ void setSeed( unsigned int seed = 0 ); //! Return a random number between -1.0 and 1.0 using rand(). virtual MY_FLOAT tick(); //! Return \e vectorSize random numbers between -1.0 and 1.0 in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Return the last computed value. MY_FLOAT lastOut() const; public: // SWAP formerly protected MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class BlowBotl \brief STK blown bottle instrument class. This class implements a helmholtz resonator (biquad filter) with a polynomial jet excitation (a la Cook). Control Change Numbers: - Noise Gain = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BOTTLE_H) #define __BOTTLE_H class BlowBotl : public Instrmnt { public: //! Class constructor. BlowBotl(); //! Class destructor. ~BlowBotl(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Apply breath velocity to instrument void startBlowing(MY_FLOAT amplitude) { startBlowing ( amplitude, m_rate ); } //chuck //! Apply breath velocity to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath velocity with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // chuck t_CKFLOAT m_rate; t_CKFLOAT m_noiseGain; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_volume; void setVibratoFreq(MY_FLOAT freq) { vibrato->setFrequency( freq ); m_vibratoFreq = vibrato->m_freq; } void setVibratoGain(MY_FLOAT gain) { vibratoGain = gain; m_vibratoGain = vibratoGain; } void setNoiseGain(MY_FLOAT gain) { noiseGain = gain; m_noiseGain = gain; } JetTabl *jetTable; BiQuad *resonator; PoleZero *dcBlock; Noise *noise; ADSR *adsr; WaveLoop *vibrato; MY_FLOAT maxPressure; MY_FLOAT noiseGain; MY_FLOAT vibratoGain; MY_FLOAT outputGain; }; #endif /***************************************************/ /*! \class ReedTabl \brief STK reed table class. This class implements a simple one breakpoint, non-linear reed function, as described by Smith (1986). This function is based on a memoryless non-linear spring model of the reed (the reed mass is ignored) which saturates when the reed collides with the mouthpiece facing. See McIntyre, Schumacher, & Woodhouse (1983), Smith (1986), Hirschman, Cook, Scavone, and others for more information. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__REEDTABL_H) #define __REEDTABL_H class ReedTabl : public Stk { public: //! Default constructor. ReedTabl(); //! Class destructor. ~ReedTabl(); //! Set the table offset value. /*! The table offset roughly corresponds to the size of the initial reed tip opening (a greater offset represents a smaller opening). */ void setOffset(MY_FLOAT aValue); //! Set the table slope value. /*! The table slope roughly corresponds to the reed stiffness (a greater slope represents a harder reed). */ void setSlope(MY_FLOAT aValue); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the function value for \e input. /*! The function input represents the differential pressure across the reeds. */ MY_FLOAT tick(MY_FLOAT input); //! Take \e vectorSize inputs and return the corresponding function values in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected MY_FLOAT offSet; MY_FLOAT slope; MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class OneZero \brief STK one-zero filter class. This protected Filter subclass implements a one-zero digital filter. A method is provided for setting the zero position along the real axis of the z-plane while maintaining a constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__ONEZERO_H) #define __ONEZERO_H class OneZero : public FilterStk // formerly protected Filter { public: //! Default constructor creates a first-order low-pass filter. OneZero(); //! Overloaded constructor which sets the zero position during instantiation. OneZero(MY_FLOAT theZero); //! Class destructor. ~OneZero(); //! Clears the internal state of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the b[1] coefficient value. void setB1(MY_FLOAT b1); //! Set the zero position in the z-plane. /*! This method sets the zero position along the real-axis of the z-plane and normalizes the coefficients for a maximum gain of one. A positive zero value produces a high-pass filter, while a negative zero value produces a low-pass filter. This method does not affect the filter \e gain value. */ void setZero(MY_FLOAT theZero); //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class BlowHole \brief STK clarinet physical model with one register hole and one tonehole. This class is based on the clarinet model, with the addition of a two-port register hole and a three-port dynamic tonehole implementation, as discussed by Scavone and Cook (1998). In this implementation, the distances between the reed/register hole and tonehole/bell are fixed. As a result, both the tonehole and register hole will have variable influence on the playing frequency, which is dependent on the length of the air column. In addition, the highest playing freqeuency is limited by these fixed lengths. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Reed Stiffness = 2 - Noise Gain = 4 - Tonehole State = 11 - Register State = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BLOWHOLE_H) #define __BLOWHOLE_H class BlowHole : public Instrmnt { public: //! Class constructor. BlowHole(MY_FLOAT lowestFrequency); //! Class destructor. ~BlowHole(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the tonehole state (0.0 = closed, 1.0 = fully open). void setTonehole(MY_FLOAT newValue); //! Set the register hole state (0.0 = closed, 1.0 = fully open). void setVent(MY_FLOAT newValue); //! Apply breath velocity to instrument void startBlowing(MY_FLOAT amplitude) { startBlowing ( amplitude, m_rate ); } //chuck //! Apply breath pressure to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath pressure with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn( MY_FLOAT amplitude ) { noteOn ( m_frequency, amplitude ); } void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // CHUCK t_CKFLOAT m_reed; t_CKFLOAT m_noiseGain; t_CKFLOAT m_tonehole; t_CKFLOAT m_vent; t_CKFLOAT m_pressure; t_CKFLOAT m_rate; DelayL *delays[3]; ReedTabl *reedTable; OneZero *filter; PoleZero *tonehole; PoleZero *vent; Envelope *envelope; Noise *noise; WaveLoop *vibrato; long length; MY_FLOAT scatter; MY_FLOAT th_coeff; MY_FLOAT r_th; MY_FLOAT rh_coeff; MY_FLOAT rh_gain; MY_FLOAT outputGain; MY_FLOAT noiseGain; MY_FLOAT vibratoGain; }; #endif /***************************************************/ /*! \class OnePole \brief STK one-pole filter class. This protected Filter subclass implements a one-pole digital filter. A method is provided for setting the pole position along the real axis of the z-plane while maintaining a constant peak filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__ONEPOLE_H) #define __ONEPOLE_H class OnePole : public FilterStk // formerly protected Filter { public: //! Default constructor creates a first-order low-pass filter. OnePole(); //! Overloaded constructor which sets the pole position during instantiation. OnePole(MY_FLOAT thePole); //! Class destructor. ~OnePole(); //! Clears the internal state of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the a[1] coefficient value. void setA1(MY_FLOAT a1); //! Set the pole position in the z-plane. /*! This method sets the pole position along the real-axis of the z-plane and normalizes the coefficients for a maximum gain of one. A positive pole value produces a low-pass filter, while a negative pole value produces a high-pass filter. This method does not affect the filter \e gain value. */ void setPole(MY_FLOAT thePole); //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class Bowed \brief STK bowed string instrument class. This class implements a bowed string model, a la Smith (1986), after McIntyre, Schumacher, Woodhouse (1983). This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Bow Pressure = 2 - Bow Position = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BOWED_H) #define __BOWED_H class Bowed : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Bowed(MY_FLOAT lowestFrequency); //! Class destructor. ~Bowed(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set vibrato gain. void setVibrato(MY_FLOAT gain); void startBowing(MY_FLOAT amplitude) { startBowing(amplitude, m_rate ); } //! Apply breath pressure to instrument with given amplitude and rate of increase. void startBowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath pressure with given rate of decrease. void stopBowing(MY_FLOAT rate); void noteOn(MY_FLOAT amplitude) { noteOn ( m_frequency, amplitude ); } //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // CHUCK t_CKFLOAT m_bowPressure; t_CKFLOAT m_bowPosition; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_volume; t_CKFLOAT m_rate; void setVibratoFreq(MY_FLOAT freq) { vibrato->setFrequency( freq ); m_vibratoFreq = vibrato->m_freq; } void setVibratoGain(MY_FLOAT gain) { vibratoGain = gain; m_vibratoGain = vibratoGain; } DelayL *neckDelay; DelayL *bridgeDelay; BowTabl *bowTable; OnePole *stringFilter; BiQuad *bodyFilter; WaveLoop *vibrato; ADSR *adsr; MY_FLOAT maxVelocity; MY_FLOAT baseDelay; MY_FLOAT vibratoGain; MY_FLOAT betaRatio; }; #endif /***************************************************/ /*! \class DelayA \brief STK allpass interpolating delay line class. This Delay subclass implements a fractional- length digital delay-line using a first-order allpass filter. A fixed maximum length of 4095 and a delay of 0.5 is set using the default constructor. Alternatively, the delay and maximum length can be set during instantiation with an overloaded constructor. An allpass filter has unity magnitude gain but variable phase delay properties, making it useful in achieving fractional delays without affecting a signal's frequency magnitude response. In order to achieve a maximally flat phase delay response, the minimum delay possible in this implementation is limited to a value of 0.5. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__DelayA_h) #define __DelayA_h class DelayA : public Delay { public: //! Default constructor creates a delay-line with maximum length of 4095 samples and zero delay. DelayA(); //! Overloaded constructor which specifies the current and maximum delay-line lengths. DelayA(MY_FLOAT theDelay, long maxDelay); //! Class destructor. ~DelayA(); //! Clears the internal state of the delay line. void clear(); //! Set the delay-line length /*! The valid range for \e theDelay is from 0.5 to the maximum delay-line length. */ void setDelay(MY_FLOAT theDelay); void set( MY_FLOAT delay, long max ); //! Return the value which will be output by the next call to tick(). /*! This method is valid only for delay settings greater than zero! */ MY_FLOAT nextOut(void); //! Input one sample to the delay-line and return one output. MY_FLOAT tick(MY_FLOAT sample); public: // SWAP formerly protected MY_FLOAT alpha; MY_FLOAT coeff; MY_FLOAT apInput; MY_FLOAT nextOutput; bool doNextOut; }; #endif /***************************************************/ /*! \class Brass \brief STK simple brass instrument class. This class implements a simple brass instrument waveguide model, a la Cook (TBone, HosePlayer). This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Lip Tension = 2 - Slide Length = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Volume = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__BRASS_H) #define __BRASS_H class Brass: public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Brass(MY_FLOAT lowestFrequency); //! Class destructor. ~Brass(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the lips frequency. void setLip(MY_FLOAT frequency); //! Apply breath pressure to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude,MY_FLOAT rate); //! Decrease breath pressure with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // CHUCK t_CKFLOAT m_rate; t_CKFLOAT m_lip; t_CKFLOAT m_slide; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_volume; void setVibratoFreq(MY_FLOAT freq) { vibrato->setFrequency( freq ); m_vibratoFreq = vibrato->m_freq; } void setVibratoGain(MY_FLOAT gain) { vibratoGain = gain; m_vibratoGain = vibratoGain; } DelayA *delayLine; BiQuad *lipFilter; PoleZero *dcBlock; ADSR *adsr; WaveLoop *vibrato; long length; MY_FLOAT lipTarget; MY_FLOAT slideTarget; MY_FLOAT vibratoGain; MY_FLOAT maxPressure; }; #endif /***************************************************/ /*! \class Chorus \brief STK chorus effect class. This class implements a chorus effect. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__CHORUS_H) #define __CHORUS_H class Chorus : public Stk { public: //! Class constructor, taking the longest desired delay length. Chorus(MY_FLOAT baseDelay); //! Class destructor. ~Chorus(); //! Reset and clear all internal state. void clear(); //! Set modulation depth. void setModDepth(MY_FLOAT depth); //! Set modulation frequency. void setModFrequency(MY_FLOAT frequency); //! Set the mixture of input and processed levels in the output (0.0 = input only, 1.0 = processed only). void setEffectMix(MY_FLOAT mix); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the last left output value. MY_FLOAT lastOutLeft() const; //! Return the last right output value. MY_FLOAT lastOutRight() const; //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected DelayL *delayLine[2]; WaveLoop *mods[2]; MY_FLOAT baseLength; MY_FLOAT modDepth; MY_FLOAT lastOutput[2]; MY_FLOAT effectMix; }; #endif /***************************************************/ /*! \class Clarinet \brief STK clarinet physical model class. This class implements a simple clarinet physical model, as discussed by Smith (1986), McIntyre, Schumacher, Woodhouse (1983), and others. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Reed Stiffness = 2 - Noise Gain = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__CLARINET_H) #define __CLARINET_H class Clarinet : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Clarinet(MY_FLOAT lowestFrequency); //! Class destructor. ~Clarinet(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Apply breath pressure to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath pressure with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // CHUCK t_CKFLOAT m_reed; t_CKFLOAT m_noiseGain; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_volume; t_CKFLOAT m_rate; void setVibratoFreq(MY_FLOAT freq) { vibrato->setFrequency( freq ); m_vibratoFreq = vibrato->m_freq; } void setVibratoGain(MY_FLOAT gain) { vibratoGain = gain; m_vibratoGain = vibratoGain; } void setNoiseGain(MY_FLOAT gain) { noiseGain = gain; m_noiseGain = gain; } DelayL *delayLine; ReedTabl *reedTable; OneZero *filter; Envelope *envelope; Noise *noise; WaveLoop *vibrato; long length; MY_FLOAT outputGain; MY_FLOAT noiseGain; MY_FLOAT vibratoGain; }; #endif /***************************************************/ /*! \class Drummer \brief STK drum sample player class. This class implements a drum sampling synthesizer using WvIn objects and one-pole filters. The drum rawwave files are sampled at 22050 Hz, but will be appropriately interpolated for other sample rates. You can specify the maximum polyphony (maximum number of simultaneous voices) via a #define in the Drummer.h. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__DRUMMER_H) #define __DRUMMER_H #define DRUM_NUMWAVES 11 #define DRUM_POLYPHONY 4 class Drummer : public Instrmnt { public: //! Class constructor. Drummer(); //! Class destructor. ~Drummer(); //! Start a note with the given drum type and amplitude. /*! Use general MIDI drum instrument numbers, converted to frequency values as if MIDI note numbers, to select a particular instrument. */ void noteOn(MY_FLOAT instrument, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); public: // SWAP formerly protected WvIn *waves[DRUM_POLYPHONY]; OnePole *filters[DRUM_POLYPHONY]; int sounding[DRUM_POLYPHONY]; int nSounding; }; #endif /***************************************************/ /*! \class Echo \brief STK echo effect class. This class implements a echo effect. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__ECHO_H) #define __ECHO_H class Echo : public Stk { public: //! Class constructor, taking the longest desired delay length. Echo(MY_FLOAT longestDelay); //! Class destructor. ~Echo(); //! Reset and clear all internal state. void clear(); //! Set the delay line length in samples. void setDelay(MY_FLOAT delay); void set(MY_FLOAT max); MY_FLOAT getDelay(); //! Set the mixture of input and processed levels in the output (0.0 = input only, 1.0 = processed only). void setEffectMix(MY_FLOAT mix); //! Return the last output value. MY_FLOAT lastOut() const; //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: Delay *delayLine; long length; MY_FLOAT lastOutput; MY_FLOAT effectMix; }; #endif /***************************************************/ /*! \class FMVoices \brief STK singing FM synthesis instrument. This class implements 3 carriers and a common modulator, also referred to as algorithm 6 of the TX81Z. \code Algorithm 6 is : /->1 -\ 4-|-->2 - +-> Out \->3 -/ \endcode Control Change Numbers: - Vowel = 2 - Spectral Tilt = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__FMVOICES_H) #define __FMVOICES_H class FMVoices : public FM { public: //! Class constructor. FMVoices(); //! Class destructor. ~FMVoices(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn( MY_FLOAT amplitude) { noteOn(baseFrequency, amplitude); } //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected int currentVowel; MY_FLOAT tilt[3]; MY_FLOAT mods[3]; }; #endif /***************************************************/ /*! \class Flute \brief STK flute physical model class. This class implements a simple flute physical model, as discussed by Karjalainen, Smith, Waryznyk, etc. The jet model uses a polynomial, a la Cook. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Jet Delay = 2 - Noise Gain = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__FLUTE_H) #define __FLUTE_H class Flute : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Flute(MY_FLOAT lowestFrequency); //! Class destructor. ~Flute(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the reflection coefficient for the jet delay (-1.0 - 1.0). void setJetReflection(MY_FLOAT coefficient); //! Set the reflection coefficient for the air column delay (-1.0 - 1.0). void setEndReflection(MY_FLOAT coefficient); //! Set the length of the jet delay in terms of a ratio of jet delay to air column delay lengths. void setJetDelay(MY_FLOAT aRatio); //! Apply breath velocity to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath velocity with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // CHUCK t_CKFLOAT m_jetDelay; t_CKFLOAT m_jetReflection; t_CKFLOAT m_endReflection; t_CKFLOAT m_noiseGain; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_pressure; t_CKFLOAT m_rate; void setVibratoFreq(MY_FLOAT freq) { vibrato->setFrequency( freq ); m_vibratoFreq = vibrato->m_freq; } void setVibratoGain(MY_FLOAT gain) { vibratoGain = gain; m_vibratoGain = vibratoGain; } void setNoiseGain(MY_FLOAT gain) { noiseGain = gain; m_noiseGain = gain; } DelayL *jetDelay; DelayL *boreDelay; JetTabl *jetTable; OnePole *filter; PoleZero *dcBlock; Noise *noise; ADSR *adsr; WaveLoop *vibrato; long length; MY_FLOAT lastFrequency; MY_FLOAT maxPressure; MY_FLOAT jetReflection; MY_FLOAT endReflection; MY_FLOAT noiseGain; MY_FLOAT vibratoGain; MY_FLOAT outputGain; MY_FLOAT jetRatio; }; #endif /***************************************************/ /*! \class FormSwep \brief STK sweepable formant filter class. This public BiQuad filter subclass implements a formant (resonance) which can be "swept" over time from one frequency setting to another. It provides methods for controlling the sweep rate and target frequency. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__FORMSWEP_H) #define __FORMSWEP_H class FormSwep : public BiQuad { public: //! Default constructor creates a second-order pass-through filter. FormSwep(); //! Class destructor. ~FormSwep(); //! Sets the filter coefficients for a resonance at \e frequency (in Hz). /*! This method determines the filter coefficients corresponding to two complex-conjugate poles with the given \e frequency (in Hz) and \e radius from the z-plane origin. The filter zeros are placed at z = 1, z = -1, and the coefficients are then normalized to produce a constant unity gain (independent of the filter \e gain parameter). The resulting filter frequency response has a resonance at the given \e frequency. The closer the poles are to the unit-circle (\e radius close to one), the narrower the resulting resonance width. */ void setResonance(MY_FLOAT aFrequency, MY_FLOAT aRadius); //! Set both the current and target resonance parameters. void setStates(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain = 1.0); //! Set target resonance parameters. void setTargets(MY_FLOAT aFrequency, MY_FLOAT aRadius, MY_FLOAT aGain = 1.0); //! Set the sweep rate (between 0.0 - 1.0). /*! The formant parameters are varied in increments of the sweep rate between their current and target values. A sweep rate of 1.0 will produce an immediate change in resonance parameters from their current values to the target values. A sweep rate of 0.0 will produce no change in resonance parameters. */ void setSweepRate(MY_FLOAT aRate); //! Set the sweep rate in terms of a time value in seconds. /*! This method adjusts the sweep rate based on a given time for the formant parameters to reach their target values. */ void setSweepTime(MY_FLOAT aTime); //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected bool dirty; MY_FLOAT frequency; MY_FLOAT radius; MY_FLOAT startFrequency; MY_FLOAT startRadius; MY_FLOAT startGain; MY_FLOAT targetFrequency; MY_FLOAT targetRadius; MY_FLOAT targetGain; MY_FLOAT deltaFrequency; MY_FLOAT deltaRadius; MY_FLOAT deltaGain; MY_FLOAT sweepState; MY_FLOAT sweepRate; }; #endif /***************************************************/ /*! \class HevyMetl \brief STK heavy metal FM synthesis instrument. This class implements 3 cascade operators with feedback modulation, also referred to as algorithm 3 of the TX81Z. \code Algorithm 3 is : 4--\ 3-->2-- + -->1-->Out \endcode Control Change Numbers: - Total Modulator Index = 2 - Modulator Crossfade = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__HEVYMETL_H) #define __HEVYMETL_H class HevyMetl : public FM { public: //! Class constructor. HevyMetl(); //! Class destructor. ~HevyMetl(); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn( MY_FLOAT amplitude) { noteOn(baseFrequency, amplitude); } //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class Reverb \brief STK abstract reverberator parent class. This class provides common functionality for STK reverberator subclasses. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__REVERB_H) #define __REVERB_H class Reverb : public Stk { public: //! Class constructor. Reverb(); //! Class destructor. virtual ~Reverb(); //! Reset and clear all internal state. virtual void clear() = 0; //! Set the mixture of input and "reverberated" levels in the output (0.0 = input only, 1.0 = reverb only). void setEffectMix(MY_FLOAT mix); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the last left output value. MY_FLOAT lastOutLeft() const; //! Return the last right output value. MY_FLOAT lastOutRight() const; //! Abstract tick function ... must be implemented in subclasses. virtual MY_FLOAT tick(MY_FLOAT input) = 0; //! Take \e vectorSize inputs, compute the same number of outputs and return them in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected // Returns true if argument value is prime. bool isPrime(int number); MY_FLOAT lastOutput[2]; MY_FLOAT effectMix; }; #endif // defined(__REVERB_H) /***************************************************/ /*! \class JCRev \brief John Chowning's reverberator class. This class is derived from the CLM JCRev function, which is based on the use of networks of simple allpass and comb delay filters. This class implements three series allpass units, followed by four parallel comb filters, and two decorrelation delay lines in parallel at the output. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__JCREV_H) #define __JCREV_H class JCRev : public Reverb { public: //! Class constructor taking a T60 decay time argument. JCRev(MY_FLOAT T60); //! Class destructor. ~JCRev(); //! Reset and clear all internal state. void clear(); //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); public: // SWAP formerly protected Delay *allpassDelays[3]; Delay *combDelays[4]; Delay *outLeftDelay; Delay *outRightDelay; MY_FLOAT allpassCoefficient; MY_FLOAT combCoefficient[4]; }; #endif /***************************************************/ /*! \class PluckTwo \brief STK enhanced plucked string model class. This class implements an enhanced two-string, plucked physical model, a la Jaffe-Smith, Smith, and others. PluckTwo is an abstract class, with no excitation specified. Therefore, it can't be directly instantiated. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PLUCKTWO_H) #define __PLUCKTWO_H class PluckTwo : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. PluckTwo(MY_FLOAT lowestFrequency); //! Class destructor. virtual ~PluckTwo(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Detune the two strings by the given factor. A value of 1.0 produces unison strings. void setDetune(MY_FLOAT detune); //! Efficient combined setting of frequency and detuning. void setFreqAndDetune(MY_FLOAT frequency, MY_FLOAT detune); //! Set the pluck or "excitation" position along the string (0.0 - 1.0). void setPluckPosition(MY_FLOAT position); //! Set the base loop gain. /*! The actual loop gain is set according to the frequency. Because of high-frequency loop filter roll-off, higher frequency settings have greater loop gains. */ void setBaseLoopGain(MY_FLOAT aGain); //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude); //! Virtual (abstract) tick function is implemented by subclasses. virtual MY_FLOAT tick() = 0; public: // SWAP formerly protected DelayA *delayLine; DelayA *delayLine2; DelayL *combDelay; OneZero *filter; OneZero *filter2; long length; MY_FLOAT loopGain; MY_FLOAT baseLoopGain; MY_FLOAT lastFrequency; MY_FLOAT lastLength; MY_FLOAT detuning; MY_FLOAT pluckAmplitude; MY_FLOAT pluckPosition; }; #endif /***************************************************/ /*! \class Mandolin \brief STK mandolin instrument model class. This class inherits from PluckTwo and uses "commuted synthesis" techniques to model a mandolin instrument. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Commuted Synthesis, in particular, is covered by patents, granted, pending, and/or applied-for. All are assigned to the Board of Trustees, Stanford University. For information, contact the Office of Technology Licensing, Stanford University. Control Change Numbers: - Body Size = 2 - Pluck Position = 4 - String Sustain = 11 - String Detuning = 1 - Microphone Position = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__MANDOLIN_H) #define __MANDOLIN_H class Mandolin : public PluckTwo { public: //! Class constructor, taking the lowest desired playing frequency. Mandolin(MY_FLOAT lowestFrequency); //! Class destructor. virtual ~Mandolin(); //! Pluck the strings with the given amplitude (0.0 - 1.0) using the current frequency. void pluck(MY_FLOAT amplitude); //! Pluck the strings with the given amplitude (0.0 - 1.0) and position (0.0 - 1.0). void pluck(MY_FLOAT amplitude,MY_FLOAT position); //! Start a note with the given frequency and amplitude (0.0 - 1.0). virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Set the body size (a value of 1.0 produces the "default" size). void setBodySize(MY_FLOAT size); //! Set the body impulse response bool setBodyIR( const char * path, bool isRaw ); //! Compute one output sample. virtual MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected WvIn *soundfile[12]; MY_FLOAT directBody; int mic; long dampTime; bool waveDone; MY_FLOAT m_bodySize; // MY_FLOAT m_stringDamping; // MY_FLOAT m_stringDetune; }; #endif /***************************************************/ /*! \class Mesh2D \brief Two-dimensional rectilinear waveguide mesh class. This class implements a rectilinear, two-dimensional digital waveguide mesh structure. For details, see Van Duyne and Smith, "Physical Modeling with the 2-D Digital Waveguide Mesh", Proceedings of the 1993 International Computer Music Conference. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - X Dimension = 2 - Y Dimension = 4 - Mesh Decay = 11 - X-Y Input Position = 1 by Julius Smith, 2000 - 2002. Revised by Gary Scavone for STK, 2002. */ /***************************************************/ #if !defined(__MESH2D_H) #define __MESH2D_H #define NXMAX ((short)(12)) #define NYMAX ((short)(12)) class Mesh2D : public Instrmnt { public: //! Class constructor, taking the x and y dimensions in samples. Mesh2D(short nX, short nY); //! Class destructor. ~Mesh2D(); //! Reset and clear all internal state. void clear(); //! Set the x dimension size in samples. void setNX(short lenX); //! Set the y dimension size in samples. void setNY(short lenY); //! Set the x, y input position on a 0.0 - 1.0 scale. void setInputPosition(MY_FLOAT xFactor, MY_FLOAT yFactor); //! Set the loss filters gains (0.0 - 1.0). void setDecay(MY_FLOAT decayFactor); //! Impulse the mesh with the given amplitude (frequency ignored). void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay) ... currently ignored. void noteOff(MY_FLOAT amplitude); //! Calculate and return the signal energy stored in the mesh. MY_FLOAT energy(); //! Compute one output sample, without adding energy to the mesh. MY_FLOAT tick(); //! Input a sample to the mesh and compute one output sample. MY_FLOAT tick(MY_FLOAT input); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected MY_FLOAT tick0(); MY_FLOAT tick1(); void clearMesh(); short NX, NY; short xInput, yInput; OnePole *filterX[NXMAX]; OnePole *filterY[NYMAX]; MY_FLOAT v[NXMAX-1][NYMAX-1]; // junction velocities MY_FLOAT vxp[NXMAX][NYMAX]; // positive-x velocity wave MY_FLOAT vxm[NXMAX][NYMAX]; // negative-x velocity wave MY_FLOAT vyp[NXMAX][NYMAX]; // positive-y velocity wave MY_FLOAT vym[NXMAX][NYMAX]; // negative-y velocity wave // Alternate buffers MY_FLOAT vxp1[NXMAX][NYMAX]; // positive-x velocity wave MY_FLOAT vxm1[NXMAX][NYMAX]; // negative-x velocity wave MY_FLOAT vyp1[NXMAX][NYMAX]; // positive-y velocity wave MY_FLOAT vym1[NXMAX][NYMAX]; // negative-y velocity wave int counter; // time in samples }; #endif /***************************************************/ /*! \class Modal \brief STK resonance model instrument. This class contains an excitation wavetable, an envelope, an oscillator, and N resonances (non-sweeping BiQuad filters), where N is set during instantiation. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__MODAL_H) #define __MODAL_H class Modal : public Instrmnt { public: //! Class constructor, taking the desired number of modes to create. Modal( int modes = 4 ); //! Class destructor. virtual ~Modal(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Set the ratio and radius for a specified mode filter. void setRatioAndRadius(int modeIndex, MY_FLOAT ratio, MY_FLOAT radius); //! Set the master gain. void setMasterGain(MY_FLOAT aGain); //! Set the direct gain. void setDirectGain(MY_FLOAT aGain); //! Set the gain for a specified mode filter. void setModeGain(int modeIndex, MY_FLOAT gain); //! Initiate a strike with the given amplitude (0.0 - 1.0). virtual void strike(MY_FLOAT amplitude); //! Damp modes with a given decay factor (0.0 - 1.0). void damp(MY_FLOAT amplitude); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. virtual MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value) = 0; public: // SWAP formerly protected // chuck t_CKFLOAT m_vibratoGain; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_volume; Envelope *envelope; WvIn *wave; BiQuad **filters; OnePole *onepole; WaveLoop *vibrato; int nModes; MY_FLOAT vibratoGain; MY_FLOAT masterGain; MY_FLOAT directGain; MY_FLOAT stickHardness; MY_FLOAT strikePosition; MY_FLOAT baseFrequency; MY_FLOAT *ratios; MY_FLOAT *radii; }; #endif /***************************************************/ /*! \class ModalBar \brief STK resonant bar instrument class. This class implements a number of different struck bar instruments. It inherits from the Modal class. Control Change Numbers: - Stick Hardness = 2 - Stick Position = 4 - Vibrato Gain = 11 - Vibrato Frequency = 7 - Volume = 128 - Modal Presets = 16 - Marimba = 0 - Vibraphone = 1 - Agogo = 2 - Wood1 = 3 - Reso = 4 - Wood2 = 5 - Beats = 6 - Two Fixed = 7 - Clump = 8 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__MODALBAR_H) #define __MODALBAR_H class ModalBar : public Modal { public: //! Class constructor. ModalBar(); //! Class destructor. ~ModalBar(); //! Set stick hardness (0.0 - 1.0). void setStickHardness(MY_FLOAT hardness); //! Set stick position (0.0 - 1.0). void setStrikePosition(MY_FLOAT position); //! Select a bar preset (currently modulo 9). void setPreset(int preset); //! Set the modulation (vibrato) depth. void setModulationDepth(MY_FLOAT mDepth); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); }; #endif /***************************************************/ /*! \class SubNoise \brief STK sub-sampled noise generator. Generates a new random number every "rate" ticks using the C rand() function. The quality of the rand() function varies from one OS to another. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SUBNOISE_H) #define __SUBNOISE_H class SubNoise : public Noise { public: //! Default constructor sets sub-sample rate to 16. SubNoise(int subRate = 16); //! Class destructor. ~SubNoise(); //! Return the current sub-sampling rate. int subRate(void) const; //! Set the sub-sampling rate. void setRate(int subRate); //! Return a sub-sampled random number between -1.0 and 1.0. MY_FLOAT tick(); public: // SWAP formerly protected int counter; int rate; }; #endif /***************************************************/ /*! \class Modulate \brief STK periodic/random modulator. This class combines random and periodic modulations to give a nice, natural human modulation function. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__MODULATE_H) #define __MODULATE_H class Modulate : public Stk { public: //! Class constructor. Modulate(); //! Class destructor. ~Modulate(); //! Reset internal state. void reset(); //! Set the periodic (vibrato) rate or frequency in Hz. void setVibratoRate(MY_FLOAT aRate); //! Set the periodic (vibrato) gain. void setVibratoGain(MY_FLOAT aGain); //! Set the random modulation gain. void setRandomGain(MY_FLOAT aGain); //! Compute one output sample. MY_FLOAT tick(); //! Return \e vectorSize outputs in \e vector. virtual MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Return the last computed output value. MY_FLOAT lastOut() const; public: // SWAP formerly protected WaveLoop *vibrato; SubNoise *noise; OnePole *filter; MY_FLOAT vibratoGain; MY_FLOAT randomGain; MY_FLOAT lastOutput; }; #endif /***************************************************/ /*! \class Sampler \brief STK sampling synthesis abstract base class. This instrument contains up to 5 attack waves, 5 looped waves, and an ADSR envelope. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SAMPLER_H) #define __SAMPLER_H class Sampler : public Instrmnt { public: //! Default constructor. Sampler(); //! Class destructor. virtual ~Sampler(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency) = 0; //! Initiate the envelopes with a key-on event and reset the attack waves. void keyOn(); //! Signal a key-off event to the envelopes. void keyOff(); //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude); //! Compute one output sample. virtual MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value) = 0; public: // SWAP formerly protected ADSR *adsr; WvIn *attacks[5]; WaveLoop *loops[5]; OnePole *filter; MY_FLOAT baseFrequency; MY_FLOAT attackRatios[5]; MY_FLOAT loopRatios[5]; MY_FLOAT attackGain; MY_FLOAT loopGain; int whichOne; }; #endif /***************************************************/ /*! \class Moog \brief STK moog-like swept filter sampling synthesis class. This instrument uses one attack wave, one looped wave, and an ADSR envelope (inherited from the Sampler class) and adds two sweepable formant (FormSwep) filters. Control Change Numbers: - Filter Q = 2 - Filter Sweep Rate = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Gain = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__MOOG_H) #define __MOOG_H class Moog : public Sampler { public: //! Class constructor. Moog(); //! Class destructor. ~Moog(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Start a note with the given frequency and amplitude. virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); virtual void noteOn(MY_FLOAT amplitude ); //CHUCK! note start note with current frequency //! Set the modulation (vibrato) speed in Hz. void setModulationSpeed(MY_FLOAT mSpeed); //! Set the modulation (vibrato) depth. void setModulationDepth(MY_FLOAT mDepth); //! Compute one output sample. virtual MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected //chuck t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_volume; FormSwep *filters[2]; MY_FLOAT modDepth; MY_FLOAT filterQ; MY_FLOAT filterRate; }; #endif /***************************************************/ /*! \class NRev \brief CCRMA's NRev reverberator class. This class is derived from the CLM NRev function, which is based on the use of networks of simple allpass and comb delay filters. This particular arrangement consists of 6 comb filters in parallel, followed by 3 allpass filters, a lowpass filter, and another allpass in series, followed by two allpass filters in parallel with corresponding right and left outputs. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__NREV_H) #define __NREV_H class NRev : public Reverb { public: //! Class constructor taking a T60 decay time argument. NRev(MY_FLOAT T60); //! Class destructor. ~NRev(); //! Reset and clear all internal state. void clear(); //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); public: // SWAP formerly protected Delay *allpassDelays[8]; Delay *combDelays[6]; MY_FLOAT allpassCoefficient; MY_FLOAT combCoefficient[6]; MY_FLOAT lowpassState; }; #endif /***************************************************/ /*! \class PRCRev \brief Perry's simple reverberator class. This class is based on some of the famous Stanford/CCRMA reverbs (NRev, KipRev), which were based on the Chowning/Moorer/Schroeder reverberators using networks of simple allpass and comb delay filters. This class implements two series allpass units and two parallel comb filters. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PRCREV_H) #define __PRCREV_H class PRCRev : public Reverb { public: //! Class constructor taking a T60 decay time argument. PRCRev(MY_FLOAT T60); //! Class destructor. ~PRCRev(); //! Reset and clear all internal state. void clear(); //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); public: // SWAP formerly protected Delay *allpassDelays[2]; Delay *combDelays[2]; MY_FLOAT allpassCoefficient; MY_FLOAT combCoefficient[2]; }; #endif /***************************************************/ /*! \class PercFlut \brief STK percussive flute FM synthesis instrument. This class implements algorithm 4 of the TX81Z. \code Algorithm 4 is : 4->3--\ 2-- + -->1-->Out \endcode Control Change Numbers: - Total Modulator Index = 2 - Modulator Crossfade = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PERCFLUT_H) #define __PERCFLUT_H class PercFlut : public FM { public: //! Class constructor. PercFlut(); //! Class destructor. ~PercFlut(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn( MY_FLOAT amplitude) { noteOn(baseFrequency, amplitude); } //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class Phonemes \brief STK phonemes table. This class does nothing other than declare a set of 32 static phoneme formant parameters and provide access to those values. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PHONEMES_H) #define __PHONEMES_H class Phonemes { public: Phonemes(void); ~Phonemes(void); //! Returns the phoneme name for the given index (0-31). static const char *name( unsigned int index ); //! Returns the voiced component gain for the given phoneme index (0-31). static MY_FLOAT voiceGain( unsigned int index ); //! Returns the unvoiced component gain for the given phoneme index (0-31). static MY_FLOAT noiseGain( unsigned int index ); //! Returns the formant frequency for the given phoneme index (0-31) and partial (0-3). static MY_FLOAT formantFrequency( unsigned int index, unsigned int partial ); //! Returns the formant radius for the given phoneme index (0-31) and partial (0-3). static MY_FLOAT formantRadius( unsigned int index, unsigned int partial ); //! Returns the formant gain for the given phoneme index (0-31) and partial (0-3). static MY_FLOAT formantGain( unsigned int index, unsigned int partial ); public: // SWAP formerly private static const char phonemeNames[][4]; static const MY_FLOAT phonemeGains[][2]; static const MY_FLOAT phonemeParameters[][4][3]; }; #endif /***************************************************/ /*! \class PitShift \brief STK simple pitch shifter effect class. This class implements a simple pitch shifter using delay lines. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PITSHIFT_H) #define __PITSHIFT_H class PitShift : public Stk { public: //! Class constructor. PitShift(); //! Class destructor. ~PitShift(); //! Reset and clear all internal state. void clear(); //! Set the pitch shift factor (1.0 produces no shift). void setShift(MY_FLOAT shift); //! Set the mixture of input and processed levels in the output (0.0 = input only, 1.0 = processed only). void setEffectMix(MY_FLOAT mix); //! Return the last output value. MY_FLOAT lastOut() const; //! Compute one output sample. MY_FLOAT tick(MY_FLOAT input); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected //chuck t_CKFLOAT m_vibratoGain; t_CKFLOAT m_vibratoFreq; t_CKFLOAT m_volume; DelayL *delayLine[2]; MY_FLOAT lastOutput; MY_FLOAT delay[2]; MY_FLOAT env[2]; MY_FLOAT effectMix; MY_FLOAT rate; }; #endif /***************************************************/ /*! \class Plucked \brief STK plucked string model class. This class implements a simple plucked string physical model based on the Karplus-Strong algorithm. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. There exist at least two patents, assigned to Stanford, bearing the names of Karplus and/or Strong. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__PLUCKED_H) #define __PLUCKED_H class Plucked : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Plucked(MY_FLOAT lowestFrequency); //! Class destructor. ~Plucked(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Pluck the string with the given amplitude using the current frequency. void pluck(MY_FLOAT amplitude); //! Start a note with the given frequency and amplitude. virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude); //! Compute one output sample. virtual MY_FLOAT tick(); public: // SWAP formerly protected DelayA *delayLine; OneZero *loopFilter; OnePole *pickFilter; Noise *noise; long length; MY_FLOAT loopGain; }; #endif /***************************************************/ /*! \class Resonate \brief STK noise driven formant filter. This instrument contains a noise source, which excites a biquad resonance filter, with volume controlled by an ADSR. Control Change Numbers: - Resonance Frequency (0-Nyquist) = 2 - Pole Radii = 4 - Notch Frequency (0-Nyquist) = 11 - Zero Radii = 1 - Envelope Gain = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__RESONATE_H) #define __RESONATE_H class Resonate : public Instrmnt { public: //! Class constructor. Resonate(); //! Class destructor. ~Resonate(); //! Reset and clear all internal state. void clear(); //! Set the filter for a resonance at the given frequency (Hz) and radius. void setResonance(MY_FLOAT frequency, MY_FLOAT radius); //! Set the filter for a notch at the given frequency (Hz) and radius. void setNotch(MY_FLOAT frequency, MY_FLOAT radius); //! Set the filter zero coefficients for contant resonance gain. void setEqualGainZeroes(); //! Initiate the envelope with a key-on event. void keyOn(); //! Signal a key-off event to the envelope. void keyOff(); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected ADSR *adsr; BiQuad *filter; Noise *noise; MY_FLOAT poleFrequency; MY_FLOAT poleRadius; MY_FLOAT zeroFrequency; MY_FLOAT zeroRadius; }; #endif /***************************************************/ /*! \class Rhodey \brief STK Fender Rhodes electric piano FM synthesis instrument. This class implements two simple FM Pairs summed together, also referred to as algorithm 5 of the TX81Z. \code Algorithm 5 is : 4->3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__RHODEY_H) #define __RHODEY_H class Rhodey : public FM { public: //! Class constructor. Rhodey(); //! Class destructor. ~Rhodey(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn(MY_FLOAT amplitude) { noteOn(baseFrequency * 0.5, amplitude ); } //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class SKINI \brief STK SKINI parsing class This class parses SKINI formatted text messages. It can be used to parse individual messages or it can be passed an entire file. The file specification is Perry's and his alone, but it's all text so it shouldn't be to hard to figure out. SKINI (Synthesis toolKit Instrument Network Interface) is like MIDI, but allows for floating-point control changes, note numbers, etc. The following example causes a sharp middle C to be played with a velocity of 111.132: \code noteOn 60.01 111.13 \endcode \sa \ref skini by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SKINI_H) #define __SKINI_H #include class SKINI : public Stk { public: //! Default constructor used for parsing messages received externally. SKINI(); //! Overloaded constructor taking a SKINI formatted scorefile. SKINI(char *fileName); //! Class destructor ~SKINI(); //! Attempt to parse the given string, returning the message type. /*! A type value equal to zero indicates an invalid message. */ long parseThis(char* aString); //! Parse the next message (if a file is loaded) and return the message type. /*! A negative value is returned when the file end is reached. */ long nextMessage(); //! Return the current message type. long getType() const; //! Return the current message channel value. long getChannel() const; //! Return the current message delta time value (in seconds). MY_FLOAT getDelta() const; //! Return the current message byte two value. MY_FLOAT getByteTwo() const; //! Return the current message byte three value. MY_FLOAT getByteThree() const; //! Return the current message byte two value (integer). long getByteTwoInt() const; //! Return the current message byte three value (integer). long getByteThreeInt() const; //! Return remainder string after parsing. const char* getRemainderString(); //! Return the message type as a string. const char* getMessageTypeString(); //! Return the SKINI type string for the given type value. const char* whatsThisType(long type); //! Return the SKINI controller string for the given controller number. const char* whatsThisController(long number); public: // SWAP formerly protected FILE *myFile; long messageType; char msgTypeString[64]; long channel; MY_FLOAT deltaTime; MY_FLOAT byteTwo; MY_FLOAT byteThree; long byteTwoInt; long byteThreeInt; char remainderString[1024]; char whatString[1024]; }; static const double Midi2Pitch[129] = { 8.18,8.66,9.18,9.72,10.30,10.91,11.56,12.25, 12.98,13.75,14.57,15.43,16.35,17.32,18.35,19.45, 20.60,21.83,23.12,24.50,25.96,27.50,29.14,30.87, 32.70,34.65,36.71,38.89,41.20,43.65,46.25,49.00, 51.91,55.00,58.27,61.74,65.41,69.30,73.42,77.78, 82.41,87.31,92.50,98.00,103.83,110.00,116.54,123.47, 130.81,138.59,146.83,155.56,164.81,174.61,185.00,196.00, 207.65,220.00,233.08,246.94,261.63,277.18,293.66,311.13, 329.63,349.23,369.99,392.00,415.30,440.00,466.16,493.88, 523.25,554.37,587.33,622.25,659.26,698.46,739.99,783.99, 830.61,880.00,932.33,987.77,1046.50,1108.73,1174.66,1244.51, 1318.51,1396.91,1479.98,1567.98,1661.22,1760.00,1864.66,1975.53, 2093.00,2217.46,2349.32,2489.02,2637.02,2793.83,2959.96,3135.96, 3322.44,3520.00,3729.31,3951.07,4186.01,4434.92,4698.64,4978.03, 5274.04,5587.65,5919.91,6271.93,6644.88,7040.00,7458.62,7902.13, 8372.02,8869.84,9397.27,9956.06,10548.08,11175.30,11839.82,12543.85, 13289.75}; #endif /***************************************************/ /*! \class Saxofony \brief STK faux conical bore reed instrument class. This class implements a "hybrid" digital waveguide instrument that can generate a variety of wind-like sounds. It has also been referred to as the "blowed string" model. The waveguide section is essentially that of a string, with one rigid and one lossy termination. The non-linear function is a reed table. The string can be "blown" at any point between the terminations, though just as with strings, it is impossible to excite the system at either end. If the excitation is placed at the string mid-point, the sound is that of a clarinet. At points closer to the "bridge", the sound is closer to that of a saxophone. See Scavone (2002) for more details. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Reed Stiffness = 2 - Reed Aperture = 26 - Noise Gain = 4 - Blow Position = 11 - Vibrato Frequency = 29 - Vibrato Gain = 1 - Breath Pressure = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SAXOFONY_H) #define __SAXOFONY_H class Saxofony : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Saxofony(MY_FLOAT lowestFrequency); //! Class destructor. ~Saxofony(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the "blowing" position between the air column terminations (0.0 - 1.0). void setBlowPosition(MY_FLOAT aPosition); //! Apply breath pressure to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath pressure with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // chuck t_CKFLOAT m_rate; t_CKFLOAT m_stiffness; t_CKFLOAT m_aperture; t_CKFLOAT m_noiseGain; t_CKFLOAT m_vibratoGain; t_CKFLOAT m_pressure; DelayL *delays[2]; ReedTabl *reedTable; OneZero *filter; Envelope *envelope; Noise *noise; WaveLoop *vibrato; long length; MY_FLOAT outputGain; MY_FLOAT noiseGain; MY_FLOAT vibratoGain; MY_FLOAT position; }; #endif /***************************************************/ /*! \class Shakers \brief PhISEM and PhOLIES class. PhISEM (Physically Informed Stochastic Event Modeling) is an algorithmic approach for simulating collisions of multiple independent sound producing objects. This class is a meta-model that can simulate a Maraca, Sekere, Cabasa, Bamboo Wind Chimes, Water Drops, Tambourine, Sleighbells, and a Guiro. PhOLIES (Physically-Oriented Library of Imitated Environmental Sounds) is a similar approach for the synthesis of environmental sounds. This class implements simulations of breaking sticks, crunchy snow (or not), a wrench, sandpaper, and more. Control Change Numbers: - Shake Energy = 2 - System Decay = 4 - Number Of Objects = 11 - Resonance Frequency = 1 - Shake Energy = 128 - Instrument Selection = 1071 - Maraca = 0 - Cabasa = 1 - Sekere = 2 - Guiro = 3 - Water Drops = 4 - Bamboo Chimes = 5 - Tambourine = 6 - Sleigh Bells = 7 - Sticks = 8 - Crunch = 9 - Wrench = 10 - Sand Paper = 11 - Coke Can = 12 - Next Mug = 13 - Penny + Mug = 14 - Nickle + Mug = 15 - Dime + Mug = 16 - Quarter + Mug = 17 - Franc + Mug = 18 - Peso + Mug = 19 - Big Rocks = 20 - Little Rocks = 21 - Tuned Bamboo Chimes = 22 by Perry R. Cook, 1996 - 1999. */ /***************************************************/ #if !defined(__SHAKERS_H) #define __SHAKERS_H #define MAX_FREQS 8 #define NUM_INSTR 24 class Shakers : public Instrmnt { public: //! Class constructor. Shakers(); //! Class destructor. ~Shakers(); //! Start a note with the given instrument and amplitude. /*! Use the instrument numbers above, converted to frequency values as if MIDI note numbers, to select a particular instrument. */ virtual void ck_noteOn(MY_FLOAT amplitude ); // chuck single arg call virtual void noteOn(MY_FLOAT instrument, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); int m_noteNum; // chuck data MY_FLOAT freq; int setupName(char* instr); int setupNum(int inst); public: // SWAP formerly protected // chuck t_CKFLOAT m_energy; t_CKFLOAT m_decay; t_CKFLOAT m_objects; int setFreqAndReson(int which, MY_FLOAT freq, MY_FLOAT reson); void setDecays(MY_FLOAT sndDecay, MY_FLOAT sysDecay); void setFinalZs(MY_FLOAT z0, MY_FLOAT z1, MY_FLOAT z2); MY_FLOAT wuter_tick(); MY_FLOAT tbamb_tick(); MY_FLOAT ratchet_tick(); int instType; int ratchetPos, lastRatchetPos; MY_FLOAT shakeEnergy; MY_FLOAT inputs[MAX_FREQS]; MY_FLOAT outputs[MAX_FREQS][2]; MY_FLOAT coeffs[MAX_FREQS][2]; MY_FLOAT sndLevel; MY_FLOAT baseGain; MY_FLOAT gains[MAX_FREQS]; int nFreqs; MY_FLOAT t_center_freqs[MAX_FREQS]; MY_FLOAT center_freqs[MAX_FREQS]; MY_FLOAT resons[MAX_FREQS]; MY_FLOAT freq_rand[MAX_FREQS]; int freqalloc[MAX_FREQS]; MY_FLOAT soundDecay; MY_FLOAT systemDecay; MY_FLOAT nObjects; MY_FLOAT collLikely; MY_FLOAT totalEnergy; MY_FLOAT ratchet,ratchetDelta; MY_FLOAT finalZ[3]; MY_FLOAT finalZCoeffs[3]; MY_FLOAT defObjs[NUM_INSTR]; MY_FLOAT defDecays[NUM_INSTR]; MY_FLOAT decayScale[NUM_INSTR]; }; #endif /***************************************************/ /*! \class Simple \brief STK wavetable/noise instrument. This class combines a looped wave, a noise source, a biquad resonance filter, a one-pole filter, and an ADSR envelope to create some interesting sounds. Control Change Numbers: - Filter Pole Position = 2 - Noise/Pitched Cross-Fade = 4 - Envelope Rate = 11 - Gain = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SIMPLE_H) #define __SIMPLE_H class Simple : public Instrmnt { public: //! Class constructor. Simple(); //! Class destructor. virtual ~Simple(); //! Clear internal states. void clear(); //! Set instrument parameters for a particular frequency. virtual void setFrequency(MY_FLOAT frequency); //! Start envelope toward "on" target. void keyOn(); //! Start envelope toward "off" target. void keyOff(); //! Start a note with the given frequency and amplitude. virtual void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). virtual void noteOff(MY_FLOAT amplitude); //! Compute one output sample. virtual MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). virtual void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected ADSR *adsr; WaveLoop *loop; OnePole *filter; BiQuad *biquad; Noise *noise; MY_FLOAT baseFrequency; MY_FLOAT loopGain; }; #endif /***************************************************/ /*! \class SingWave \brief STK "singing" looped soundfile class. This class contains all that is needed to make a pitched musical sound, like a simple voice or violin. In general, it will not be used alone because of munchkinification effects from pitch shifting. It will be used as an excitation source for other instruments. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SINGWAVE_H) #define __SINGWAVE_H class SingWave : public Stk { public: //! Class constructor taking filename argument. /*! An StkError will be thrown if the file is not found, its format is unknown, or a read error occurs. */ SingWave(const char *fileName, bool raw=FALSE); //! Class destructor. ~SingWave(); //! Reset file to beginning. void reset(); //! Normalize the file to a maximum of +-1.0. void normalize(); //! Normalize the file to a maximum of \e +- peak. void normalize(MY_FLOAT peak); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the vibrato frequency in Hz. void setVibratoRate(MY_FLOAT aRate); //! Set the vibrato gain. void setVibratoGain(MY_FLOAT gain); //! Set the random-ness amount. void setRandomGain(MY_FLOAT gain); //! Set the sweep rate. void setSweepRate(MY_FLOAT aRate); //! Set the gain rate. void setGainRate(MY_FLOAT aRate); //! Set the gain target value. void setGainTarget(MY_FLOAT target); //! Start a note. void noteOn(); //! Stop a note. void noteOff(); //! Return the last output value. MY_FLOAT lastOut(); //! Compute one output sample. MY_FLOAT tick(); public: // SWAP formerly protected WaveLoop *wave; Modulate *modulator; Envelope *envelope; Envelope *pitchEnvelope; MY_FLOAT rate; MY_FLOAT sweepRate; MY_FLOAT lastOutput; MY_FLOAT m_freq; //chuck data }; #endif /***************************************************/ /*! \class Sitar \brief STK sitar string model class. This class implements a sitar plucked string physical model based on the Karplus-Strong algorithm. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. There exist at least two patents, assigned to Stanford, bearing the names of Karplus and/or Strong. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SITAR_H) #define __SITAR_H class Sitar : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. Sitar(MY_FLOAT lowestFrequency); //! Class destructor. ~Sitar(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Pluck the string with the given amplitude using the current frequency. void pluck(MY_FLOAT amplitude); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); public: // SWAP formerly protected DelayA *delayLine; OneZero *loopFilter; Noise *noise; ADSR *envelope; long length; MY_FLOAT loopGain; MY_FLOAT amGain; MY_FLOAT delay; MY_FLOAT targetDelay; }; #endif /***************************************************/ /*! \class Socket \brief STK TCP socket client/server class. This class provides a uniform cross-platform TCP socket client or socket server interface. Methods are provided for reading or writing data buffers to/from connections. This class also provides a number of static functions for use with external socket descriptors. The user is responsible for checking the values returned by the read/write methods. Values less than or equal to zero indicate a closed or lost connection or the occurence of an error. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__SOCKET_H) #define __SOCKET_H class Socket : public Stk { public: //! Default constructor which creates a local socket server on port 2006 (or the specified port number). /*! An StkError will be thrown if a socket error occurs during instantiation. */ Socket( int port = 2006 ); //! Class constructor which creates a socket client connection to the specified host and port. /*! An StkError will be thrown if a socket error occurs during instantiation. */ Socket( int port, const char *hostname ); //! The class destructor closes the socket instance, breaking any existing connections. ~Socket(); //! Connect a socket client to the specified host and port and returns the resulting socket descriptor. /*! This method is valid for socket clients only. If it is called for a socket server, -1 is returned. If the socket client is already connected, that connection is terminated and a new connection is attempted. Server connections are made using the accept() method. An StkError will be thrown if a socket error occurs during instantiation. \sa accept */ int connect( int port, const char *hostname = "localhost" ); //! Close this socket. void close( void ); //! Return the server/client socket descriptor. int socket( void ) const; //! Return the server/client port number. int port( void ) const; //! If this is a socket server, extract the first pending connection request from the queue and create a new connection, returning the descriptor for the accepted socket. /*! If no connection requests are pending and the socket has not been set non-blocking, this function will block until a connection is present. If an error occurs or this is a socket client, -1 is returned. */ int accept( void ); //! If enable = false, the socket is set to non-blocking mode. When first created, sockets are by default in blocking mode. static void setBlocking( int socket, bool enable ); //! Close the socket with the given descriptor. static void close( int socket ); //! Returns TRUE is the socket descriptor is valid. static bool isValid( int socket ); //! Write a buffer over the socket connection. Returns the number of bytes written or -1 if an error occurs. int writeBuffer(const void *buffer, long bufferSize, int flags = 0); //! Write a buffer via the specified socket. Returns the number of bytes written or -1 if an error occurs. static int writeBuffer(int socket, const void *buffer, long bufferSize, int flags ); //! Read a buffer from the socket connection, up to length \e bufferSize. Returns the number of bytes read or -1 if an error occurs. int readBuffer(void *buffer, long bufferSize, int flags = 0); //! Read a buffer via the specified socket. Returns the number of bytes read or -1 if an error occurs. static int readBuffer(int socket, void *buffer, long bufferSize, int flags ); public: // SWAP formerly protected char msg[256]; int soket; int poort; bool server; }; #endif // defined(__SOCKET_H) /***************************************************/ /*! \class Vector3D \brief STK 3D vector class. This class implements a three-dimensional vector. by Perry R. Cook, 1995 - 2002. */ /***************************************************/ #if !defined(__VECTOR3D_H) #define __VECTOR3D_H class Vector3D { public: //! Default constructor taking optional initial X, Y, and Z values. Vector3D(double initX=0.0, double initY=0.0, double initZ=0.0); //! Class destructor. ~Vector3D(); //! Get the current X value. double getX(); //! Get the current Y value. double getY(); //! Get the current Z value. double getZ(); //! Calculate the vector length. double getLength(); //! Set the X, Y, and Z values simultaniously. void setXYZ(double anX, double aY, double aZ); //! Set the X value. void setX(double aval); //! Set the Y value. void setY(double aval); //! Set the Z value. void setZ(double aval); public: // SWAP formerly protected double myX; double myY; double myZ; }; #endif /***************************************************/ /*! \class Sphere \brief STK sphere class. This class implements a spherical ball with radius, mass, position, and velocity parameters. by Perry R. Cook, 1995 - 2002. */ /***************************************************/ #if !defined(__SPHERE_H) #define __SPHERE_H class Sphere { public: //! Constructor taking an initial radius value. Sphere(double initRadius); //! Class destructor. ~Sphere(); //! Set the 3D center position of the sphere. void setPosition(double anX, double aY, double aZ); //! Set the 3D velocity of the sphere. void setVelocity(double anX, double aY, double aZ); //! Set the radius of the sphere. void setRadius(double aRadius); //! Set the mass of the sphere. void setMass(double aMass); //! Get the current position of the sphere as a 3D vector. Vector3D* getPosition(); //! Get the relative position of the given point to the sphere as a 3D vector. Vector3D* getRelativePosition(Vector3D *aPosition); //! Set the velcoity of the sphere as a 3D vector. double getVelocity(Vector3D* aVelocity); //! Returns the distance from the sphere boundary to the given position (< 0 if inside). double isInside(Vector3D *aPosition); //! Get the current sphere radius. double getRadius(); //! Get the current sphere mass. double getMass(); //! Increase the current sphere velocity by the given 3D components. void addVelocity(double anX, double aY, double aZ); //! Move the sphere for the given time increment. void tick(double timeIncrement); public: // SWAP formerly private Vector3D *myPosition; Vector3D *myVelocity; Vector3D workingVector; double myRadius; double myMass; }; #endif /***************************************************/ /*! \class StifKarp \brief STK plucked stiff string instrument. This class implements a simple plucked string algorithm (Karplus Strong) with enhancements (Jaffe-Smith, Smith, and others), including string stiffness and pluck position controls. The stiffness is modeled with allpass filters. This is a digital waveguide model, making its use possibly subject to patents held by Stanford University, Yamaha, and others. Control Change Numbers: - Pickup Position = 4 - String Sustain = 11 - String Stretch = 1 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__StifKarp_h) #define __StifKarp_h class StifKarp : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. StifKarp(MY_FLOAT lowestFrequency); //! Class destructor. ~StifKarp(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set the stretch "factor" of the string (0.0 - 1.0). void setStretch(MY_FLOAT stretch); //! Set the pluck or "excitation" position along the string (0.0 - 1.0). void setPickupPosition(MY_FLOAT position); //! Set the base loop gain. /*! The actual loop gain is set according to the frequency. Because of high-frequency loop filter roll-off, higher frequency settings have greater loop gains. */ void setBaseLoopGain(MY_FLOAT aGain); //! Pluck the string with the given amplitude using the current frequency. void pluck(MY_FLOAT amplitude); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected // chuck t_CKFLOAT m_sustain; DelayA *delayLine; DelayL *combDelay; OneZero *filter; Noise *noise; BiQuad *biQuad[4]; long length; MY_FLOAT loopGain; MY_FLOAT baseLoopGain; MY_FLOAT lastFrequency; MY_FLOAT lastLength; MY_FLOAT stretching; MY_FLOAT pluckAmplitude; MY_FLOAT pickupPosition; }; #endif /***************************************************/ /*! \class Table \brief STK table lookup class. This class loads a table of floating-point doubles, which are assumed to be in big-endian format. Linear interpolation is performed for fractional lookup indexes. An StkError will be thrown if the table file is not found. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__TABLE_H) #define __TABLE_H class Table : public Stk { public: //! Constructor loads the data from \e fileName. Table(char *fileName); //! Class destructor. ~Table(); //! Return the number of elements in the table. long getLength() const; //! Return the last output value. MY_FLOAT lastOut() const; //! Return the table value at position \e index. /*! Linear interpolation is performed if \e index is fractional. */ MY_FLOAT tick(MY_FLOAT index); //! Take \e vectorSize index positions and return the corresponding table values in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); public: // SWAP formerly protected long length; MY_FLOAT *data; MY_FLOAT lastOutput; }; #endif // defined(__TABLE_H) /***************************************************/ /*! \class WvOut \brief STK audio data output base class. This class provides output support for various audio file formats. It also serves as a base class for "realtime" streaming subclasses. WvOut writes samples to an audio file. It supports multi-channel data in interleaved format. It is important to distinguish the tick() methods, which output single samples to all channels in a sample frame, from the tickFrame() method, which takes a pointer to multi-channel sample frame data. WvOut currently supports WAV, AIFF, AIFC, SND (AU), MAT-file (Matlab), and STK RAW file formats. Signed integer (8-, 16-, and 32-bit) and floating- point (32- and 64-bit) data types are supported. STK RAW files use 16-bit integers by definition. MAT-files will always be written as 64-bit floats. If a data type specification does not match the specified file type, the data type will automatically be modified. Uncompressed data types are not supported. Currently, WvOut is non-interpolating and the output rate is always Stk::sampleRate(). by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__WVOUT_H) #define __WVOUT_H #include #define BUFFER_SIZE 1024 // sample frames class WvOut : public Stk { public: typedef unsigned long FILE_TYPE; static const FILE_TYPE WVOUT_RAW; /*!< STK RAW file type. */ static const FILE_TYPE WVOUT_WAV; /*!< WAV file type. */ static const FILE_TYPE WVOUT_SND; /*!< SND (AU) file type. */ static const FILE_TYPE WVOUT_AIF; /*!< AIFF file type. */ static const FILE_TYPE WVOUT_MAT; /*!< Matlab MAT-file type. */ //! Default constructor. WvOut(); //! Overloaded constructor used to specify a file name, type, and data format with this object. /*! An StkError is thrown for invalid argument values or if an error occurs when initializing the output file. */ WvOut( const char *fileName, unsigned int nChannels = 1, FILE_TYPE type = WVOUT_WAV, Stk::STK_FORMAT format = STK_SINT16 ); //! Class destructor. virtual ~WvOut(); //! Create a file of the specified type and name and output samples to it in the given data format. /*! An StkError is thrown for invalid argument values or if an error occurs when initializing the output file. */ void openFile( const char *fileName, unsigned int nChannels = 1, \ WvOut::FILE_TYPE type = WVOUT_WAV, Stk::STK_FORMAT = STK_SINT16 ); //! If a file is open, write out samples in the queue and then close it. void closeFile( void ); //! Return the number of sample frames output. unsigned long getFrames( void ) const; //! Return the number of seconds of data output. MY_FLOAT getTime( void ) const; //! Output a single sample to all channels in a sample frame. /*! An StkError is thrown if a file write error occurs. */ virtual void tick(const MY_FLOAT sample); //! Output each sample in \e vector to all channels in \e vectorSize sample frames. /*! An StkError is thrown if a file write error occurs. */ virtual void tick(const MY_FLOAT *vector, unsigned int vectorSize); //! Output the \e frameVector of sample frames of the given length. /*! An StkError is thrown if a file write error occurs. */ virtual void tickFrame(const MY_FLOAT *frameVector, unsigned int frames = 1); public: // SWAP formerly protected // Initialize class variables. void init( void ); // Write data to output file; virtual void writeData( unsigned long frames ); // Write STK RAW file header. bool setRawFile( const char *fileName ); // Write WAV file header. bool setWavFile( const char *fileName ); // Close WAV file, updating the header. void closeWavFile( void ); // Write SND (AU) file header. bool setSndFile( const char *fileName ); // Close SND file, updating the header. void closeSndFile( void ); // Write AIFF file header. bool setAifFile( const char *fileName ); // Close AIFF file, updating the header. void closeAifFile( void ); // Write MAT-file header. bool setMatFile( const char *fileName ); // Close MAT-file, updating the header. void closeMatFile( void ); char msg[256]; FILE *fd; MY_FLOAT *data; FILE_TYPE fileType; STK_FORMAT dataType; bool byteswap; unsigned int channels; unsigned long counter; unsigned long totalCount; // char m_filename[1024]; Chuck_String str_filename; t_CKUINT start; // char autoPrefix[1024]; Chuck_String autoPrefix; t_CKUINT flush; }; #endif // defined(__WVOUT_H) /***************************************************/ /*! \class TubeBell \brief STK tubular bell (orchestral chime) FM synthesis instrument. This class implements two simple FM Pairs summed together, also referred to as algorithm 5 of the TX81Z. \code Algorithm 5 is : 4->3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__TUBEBELL_H) #define __TUBEBELL_H class TubeBell : public FM { public: //! Class constructor. TubeBell(); //! Class destructor. ~TubeBell(); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn( MY_FLOAT amplitude) { noteOn(baseFrequency, amplitude); } //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class TwoPole \brief STK two-pole filter class. This protected Filter subclass implements a two-pole digital filter. A method is provided for creating a resonance in the frequency response while maintaining a nearly constant filter gain. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__TWOPOLE_H) #define __TWOPOLE_H class TwoPole : public FilterStk // formerly protected Filter { public: //! Default constructor creates a second-order pass-through filter. TwoPole(); //! Class destructor. ~TwoPole(); //! Clears the internal states of the filter. void clear(void); //! Set the b[0] coefficient value. void setB0(MY_FLOAT b0); //! Set the a[1] coefficient value. void setA1(MY_FLOAT a1); //! Set the a[2] coefficient value. void setA2(MY_FLOAT a2); //! Sets the filter coefficients for a resonance at \e frequency (in Hz). /*! This method determines the filter coefficients corresponding to two complex-conjugate poles with the given \e frequency (in Hz) and \e radius from the z-plane origin. If \e normalize is true, the coefficients are then normalized to produce unity gain at \e frequency (the actual maximum filter gain tends to be slightly greater than unity when \e radius is not close to one). The resulting filter frequency response has a resonance at the given \e frequency. The closer the poles are to the unit-circle (\e radius close to one), the narrower the resulting resonance width. An unstable filter will result for \e radius >= 1.0. For a better resonance filter, use a BiQuad filter. \sa BiQuad filter class */ void setResonance(MY_FLOAT frequency, MY_FLOAT radius, bool normalize = FALSE); bool m_resNorm; MY_FLOAT m_resFreq; MY_FLOAT m_resRad; void ck_setResNorm( bool n ) { m_resNorm = n; setResonance(m_resFreq, m_resRad, m_resNorm); } void ck_setResFreq( MY_FLOAT n ) { m_resFreq = n; setResonance(m_resFreq, m_resRad, m_resNorm); } void ck_setResRad( MY_FLOAT n ) { m_resRad = n; setResonance(m_resFreq, m_resRad, m_resNorm); } //! Set the filter gain. /*! The gain is applied at the filter input and does not affect the coefficient values. The default gain value is 1.0. */ void setGain(MY_FLOAT theGain); //! Return the current filter gain. MY_FLOAT getGain(void) const; //! Return the last computed output value. MY_FLOAT lastOut(void) const; //! Input one sample to the filter and return one output. MY_FLOAT tick(MY_FLOAT sample); //! Input \e vectorSize samples to the filter and return an equal number of outputs in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); }; #endif /***************************************************/ /*! \class VoicForm \brief Four formant synthesis instrument. This instrument contains an excitation singing wavetable (looping wave with random and periodic vibrato, smoothing on frequency, etc.), excitation noise, and four sweepable complex resonances. Measured formant data is included, and enough data is there to support either parallel or cascade synthesis. In the floating point case cascade synthesis is the most natural so that's what you'll find here. Control Change Numbers: - Voiced/Unvoiced Mix = 2 - Vowel/Phoneme Selection = 4 - Vibrato Frequency = 11 - Vibrato Gain = 1 - Loudness (Spectral Tilt) = 128 by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__VOICFORM_H) #define __VOICFORM_H class VoicForm : public Instrmnt { public: //! Class constructor, taking the lowest desired playing frequency. VoicForm(); //! Class destructor. ~VoicForm(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Set instrument parameters for the given phoneme. Returns FALSE if phoneme not found. bool setPhoneme(const char* phoneme); //! Set the voiced component gain. void setVoiced(MY_FLOAT vGain); //! Set the unvoiced component gain. void setUnVoiced(MY_FLOAT nGain); //! Set the sweep rate for a particular formant filter (0-3). void setFilterSweepRate(int whichOne, MY_FLOAT rate); //! Set voiced component pitch sweep rate. void setPitchSweepRate(MY_FLOAT rate); //! Start the voice. void speak(); //! Stop the voice. void quiet(); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! start at current frequency.. void noteOn( MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected int m_phonemeNum; SingWave *voiced; Noise *noise; Envelope *noiseEnv; FormSwep *filters[4]; OnePole *onepole; OneZero *onezero; Chuck_String str_phoneme; // chuck data }; #endif /***************************************************/ /*! \class Voicer \brief STK voice manager class. This class can be used to manage a group of STK instrument classes. Individual voices can be controlled via unique note tags. Instrument groups can be controlled by channel number. A previously constructed STK instrument class is linked with a voice manager using the addInstrument() function. An optional channel number argument can be specified to the addInstrument() function as well (default channel = 0). The voice manager does not delete any instrument instances ... it is the responsibility of the user to allocate and deallocate all instruments. The tick() function returns the mix of all sounding voices. Each noteOn returns a unique tag (credits to the NeXT MusicKit), so you can send control changes to specific voices within an ensemble. Alternately, control changes can be sent to all voices on a given channel. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__VOICER_H) #define __VOICER_H class Voicer : public Stk { public: //! Class constructor taking the maximum number of instruments to control and an optional note decay time (in seconds). Voicer( int maxInstruments, MY_FLOAT decayTime=0.2 ); //! Class destructor. ~Voicer(); //! Add an instrument with an optional channel number to the voice manager. /*! A set of instruments can be grouped by channel number and controlled via the functions which take a channel number argument. */ void addInstrument( Instrmnt *instrument, int channel=0 ); //! Remove the given instrument pointer from the voice manager's control. /*! It is important that any instruments which are to be deleted by the user while the voice manager is running be first removed from the manager's control via this function!! */ void removeInstrument( Instrmnt *instrument ); //! Initiate a noteOn event with the given note number and amplitude and return a unique note tag. /*! Send the noteOn message to the first available unused voice. If all voices are sounding, the oldest voice is interrupted and sent the noteOn message. If the optional channel argument is non-zero, only voices on that channel are used. If no voices are found for a specified non-zero channel value, the function returns -1. The amplitude value should be in the range 0.0 - 128.0. */ long noteOn( MY_FLOAT noteNumber, MY_FLOAT amplitude, int channel=0 ); //! Send a noteOff to all voices having the given noteNumber and optional channel (default channel = 0). /*! The amplitude value should be in the range 0.0 - 128.0. */ void noteOff( MY_FLOAT noteNumber, MY_FLOAT amplitude, int channel=0 ); //! Send a noteOff to the voice with the given note tag. /*! The amplitude value should be in the range 0.0 - 128.0. */ void noteOff( long tag, MY_FLOAT amplitude ); //! Send a frequency update message to all voices assigned to the optional channel argument (default channel = 0). /*! The \e noteNumber argument corresponds to a MIDI note number, though it is a floating-point value and can range beyond the normal 0-127 range. */ void setFrequency( MY_FLOAT noteNumber, int channel=0 ); //! Send a frequency update message to the voice with the given note tag. /*! The \e noteNumber argument corresponds to a MIDI note number, though it is a floating-point value and can range beyond the normal 0-127 range. */ void setFrequency( long tag, MY_FLOAT noteNumber ); //! Send a pitchBend message to all voices assigned to the optional channel argument (default channel = 0). void pitchBend( MY_FLOAT value, int channel=0 ); //! Send a pitchBend message to the voice with the given note tag. void pitchBend( long tag, MY_FLOAT value ); //! Send a controlChange to all instruments assigned to the optional channel argument (default channel = 0). void controlChange( int number, MY_FLOAT value, int channel=0 ); //! Send a controlChange to the voice with the given note tag. void controlChange( long tag, int number, MY_FLOAT value ); //! Send a noteOff message to all existing voices. void silence( void ); //! Mix the output for all sounding voices. MY_FLOAT tick(); //! Compute \e vectorSize output mixes and return them in \e vector. MY_FLOAT *tick(MY_FLOAT *vector, unsigned int vectorSize); //! Return the last output value. MY_FLOAT lastOut() const; //! Return the last left output value. MY_FLOAT lastOutLeft() const; //! Return the last right output value. MY_FLOAT lastOutRight() const; public: // SWAP formerly protected typedef struct { Instrmnt *instrument; long tag; MY_FLOAT noteNumber; MY_FLOAT frequency; int sounding; int channel; } Voice; int nVoices; int maxVoices; Voice *voices; long tags; int muteTime; MY_FLOAT lastOutput; MY_FLOAT lastOutputLeft; MY_FLOAT lastOutputRight; }; #endif /***************************************************/ /*! \class Whistle \brief STK police/referee whistle instrument class. This class implements a hybrid physical/spectral model of a police whistle (a la Cook). Control Change Numbers: - Noise Gain = 4 - Fipple Modulation Frequency = 11 - Fipple Modulation Gain = 1 - Blowing Frequency Modulation = 2 - Volume = 128 by Perry R. Cook 1996 - 2002. */ /***************************************************/ #if !defined(__WHISTLE_H) #define __WHISTLE_H class Whistle : public Instrmnt { public: //! Class constructor. Whistle(); //! Class destructor. ~Whistle(); //! Reset and clear all internal state. void clear(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Apply breath velocity to instrument with given amplitude and rate of increase. void startBlowing(MY_FLOAT amplitude, MY_FLOAT rate); //! Decrease breath velocity with given rate of decrease. void stopBlowing(MY_FLOAT rate); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); //! Stop a note with the given amplitude (speed of decay). void noteOff(MY_FLOAT amplitude); //! Compute one output sample. MY_FLOAT tick(); //! Perform the control change specified by \e number and \e value (0.0 - 128.0). void controlChange(int number, MY_FLOAT value); public: // SWAP formerly protected Vector3D *tempVectorP; Vector3D *tempVector; OnePole onepole; Noise noise; Envelope envelope; Sphere *can; // Declare a Spherical "can". Sphere *pea, *bumper; // One spherical "pea", and a spherical "bumper". WaveLoop *sine; MY_FLOAT baseFrequency; MY_FLOAT maxPressure; MY_FLOAT noiseGain; MY_FLOAT fippleFreqMod; MY_FLOAT fippleGainMod; MY_FLOAT blowFreqMod; MY_FLOAT tickSize; MY_FLOAT canLoss; int subSample, subSampCount; }; #endif /***************************************************/ /*! \class Wurley \brief STK Wurlitzer electric piano FM synthesis instrument. This class implements two simple FM Pairs summed together, also referred to as algorithm 5 of the TX81Z. \code Algorithm 5 is : 4->3--\ + --> Out 2->1--/ \endcode Control Change Numbers: - Modulator Index One = 2 - Crossfade of Outputs = 4 - LFO Speed = 11 - LFO Depth = 1 - ADSR 2 & 4 Target = 128 The basic Chowning/Stanford FM patent expired in 1995, but there exist follow-on patents, mostly assigned to Yamaha. If you are of the type who should worry about this (making money) worry away. by Perry R. Cook and Gary P. Scavone, 1995 - 2002. */ /***************************************************/ #if !defined(__WURLEY_H) #define __WURLEY_H class Wurley : public FM { public: //! Class constructor. Wurley(); //! Class destructor. ~Wurley(); //! Set instrument parameters for a particular frequency. void setFrequency(MY_FLOAT frequency); //! Start a note with the given frequency and amplitude. void noteOn(MY_FLOAT frequency, MY_FLOAT amplitude); void noteOn(MY_FLOAT amplitude) { noteOn ( baseFrequency, amplitude ); } // CHUCK HACK: virtual void controlChange( int which, MY_FLOAT value ); //! Compute one output sample. MY_FLOAT tick(); }; #endif /***************************************************/ /*! \class Blit \brief STK band-limited impulse train class. This class generates a band-limited impulse train using a closed-form algorithm reported by Stilson and Smith in "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. The user can specify both the fundamental frequency of the impulse train and the number of harmonics contained in the resulting signal. The signal is normalized so that the peak value is +/-1.0. If nHarmonics is 0, then the signal will contain all harmonics up to half the sample rate. Note, however, that this setting may produce aliasing in the signal when the frequency is changing (no automatic modification of the number of harmonics is performed by the setFrequency() function). Original code by Robin Davies, 2005. Revisions by Gary Scavone for STK, 2005. */ /***************************************************/ class BLT { public: virtual ~BLT() {} virtual void setPhase( MY_FLOAT phase ) = 0; virtual void setFrequency( MY_FLOAT freq ) = 0; virtual void setHarmonics( unsigned int harmonics ) = 0; t_CKFLOAT getValuePhase() { return m_phase; } t_CKFLOAT getValueFreq() { return m_freq; } t_CKINT getValueHarmonics() { return m_harmonics; } public: t_CKFLOAT m_phase; t_CKFLOAT m_freq; t_CKINT m_harmonics; }; #ifndef STK_BLIT_H #define STK_BLIT_H class Blit : public BLT { public: //! Default constructor that initializes BLIT frequency to 220 Hz. Blit( MY_FLOAT frequency = 220.0 ); //! Class destructor. virtual ~Blit(); //! Resets the oscillator state and phase to 0. void reset(); //! Set the phase of the signal. /*! Set the phase of the signal, in the range 0 to 1. */ virtual void setPhase( MY_FLOAT phase ) { phase_ = ONE_PI * phase; } //! Get the current phase of the signal. /*! Get the phase of the signal, in the range [0 to 1.0). */ MY_FLOAT getPhase() const { return phase_ / ONE_PI; } //! Set the impulse train rate in terms of a frequency in Hz. virtual void setFrequency( MY_FLOAT frequency ); //! Set the number of harmonics generated in the signal. /*! This function sets the number of harmonics contained in the resulting signal. It is equivalent to (2 * M) + 1 in the BLIT algorithm. The default value of 0 sets the algorithm for maximum harmonic content (harmonics up to half the sample rate). This parameter is not checked against the current sample rate and fundamental frequency. Thus, aliasing can result if one or more harmonics for a given fundamental frequency exceeds fs / 2. This behavior was chosen over the potentially more problematic solution of automatically modifying the M parameter, which can produce audible clicks in the signal. */ virtual void setHarmonics( unsigned int nHarmonics = 0 ); //! Compute one output sample. MY_FLOAT tick(); protected: void updateHarmonics( void ); MY_FLOAT computeSample( void ); unsigned int nHarmonics_; unsigned int m_; MY_FLOAT rate_; MY_FLOAT phase_; MY_FLOAT p_; }; #endif /***************************************************/ /*! \class BlitSaw \brief STK band-limited sawtooth wave class. This class generates a band-limited sawtooth waveform using a closed-form algorithm reported by Stilson and Smith in "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. The user can specify both the fundamental frequency of the sawtooth and the number of harmonics contained in the resulting signal. If nHarmonics is 0, then the signal will contain all harmonics up to half the sample rate. Note, however, that this setting may produce aliasing in the signal when the frequency is changing (no automatic modification of the number of harmonics is performed by the setFrequency() function). Based on initial code of Robin Davies, 2005. Modified algorithm code by Gary Scavone, 2005. */ /***************************************************/ #ifndef STK_BLITSAW_H #define STK_BLITSAW_H class BlitSaw : public BLT { public: //! Class constructor. BlitSaw( MY_FLOAT frequency = 220.0 ); //! Class destructor. virtual ~BlitSaw(); //! Resets the oscillator state and phase to 0. void reset(); //! Set the phase of the signal. /*! Set the phase of the signal, in the range 0 to 1. */ virtual void setPhase( MY_FLOAT phase ) { phase_ = ONE_PI * phase; } //! Set the sawtooth oscillator rate in terms of a frequency in Hz. virtual void setFrequency( MY_FLOAT frequency ); //! Set the number of harmonics generated in the signal. /*! This function sets the number of harmonics contained in the resulting signal. It is equivalent to (2 * M) + 1 in the BLIT algorithm. The default value of 0 sets the algorithm for maximum harmonic content (harmonics up to half the sample rate). This parameter is not checked against the current sample rate and fundamental frequency. Thus, aliasing can result if one or more harmonics for a given fundamental frequency exceeds fs / 2. This behavior was chosen over the potentially more problematic solution of automatically modifying the M parameter, which can produce audible clicks in the signal. */ virtual void setHarmonics( unsigned int nHarmonics = 0 ); //! Compute one output sample. MY_FLOAT tick(); protected: void updateHarmonics( void ); MY_FLOAT computeSample( void ); unsigned int nHarmonics_; unsigned int m_; MY_FLOAT rate_; MY_FLOAT phase_; MY_FLOAT p_; MY_FLOAT C2_; MY_FLOAT a_; MY_FLOAT state_; }; #endif /***************************************************/ /*! \class BlitSquare \brief STK band-limited square wave class. This class generates a band-limited square wave signal. It is derived in part from the approach reported by Stilson and Smith in "Alias-Free Digital Synthesis of Classic Analog Waveforms", 1996. The algorithm implemented in this class uses a SincM function with an even M value to achieve a bipolar bandlimited impulse train. This signal is then integrated to achieve a square waveform. The integration process has an associated DC offset but that is subtracted off the output signal. The user can specify both the fundamental frequency of the waveform and the number of harmonics contained in the resulting signal. If nHarmonics is 0, then the signal will contain all harmonics up to half the sample rate. Note, however, that this setting may produce aliasing in the signal when the frequency is changing (no automatic modification of the number of harmonics is performed by the setFrequency() function). Based on initial code of Robin Davies, 2005. Modified algorithm code by Gary Scavone, 2005. */ /***************************************************/ #ifndef STK_BLITSQUARE_H #define STK_BLITSQUARE_H class BlitSquare : public BLT { public: //! Default constructor that initializes BLIT frequency to 220 Hz. BlitSquare( MY_FLOAT frequency = 220.0 ); //! Class destructor. virtual ~BlitSquare(); //! Resets the oscillator state and phase to 0. void reset(); //! Set the phase of the signal. /*! Set the phase of the signal, in the range 0 to 1. */ virtual void setPhase( MY_FLOAT phase ) { phase_ = ONE_PI * phase; } //! Get the current phase of the signal. /*! Get the phase of the signal, in the range [0 to 1.0). */ MY_FLOAT getPhase() const { return phase_ / ONE_PI; } //! Set the impulse train rate in terms of a frequency in Hz. virtual void setFrequency( MY_FLOAT frequency ); //! Set the number of harmonics generated in the signal. /*! This function sets the number of harmonics contained in the resulting signal. It is equivalent to (2 * M) + 1 in the BLIT algorithm. The default value of 0 sets the algorithm for maximum harmonic content (harmonics up to half the sample rate). This parameter is not checked against the current sample rate and fundamental frequency. Thus, aliasing can result if one or more harmonics for a given fundamental frequency exceeds fs / 2. This behavior was chosen over the potentially more problematic solution of automatically modifying the M parameter, which can produce audible clicks in the signal. */ virtual void setHarmonics( unsigned int nHarmonics = 0 ); //! Compute one output sample. MY_FLOAT tick(); protected: void updateHarmonics( void ); MY_FLOAT computeSample( void ); unsigned int nHarmonics_; unsigned int m_; MY_FLOAT rate_; MY_FLOAT phase_; MY_FLOAT a_; MY_FLOAT p_; MY_FLOAT offset_; MY_FLOAT m_boutput; MY_FLOAT m_output; MY_FLOAT dcbState_; }; #endif /*********************************************************/ /* Definition of SKINI Message Types and Special Symbols Synthesis toolKit Instrument Network Interface These symbols should have the form __SK__ Where is the string used in the SKINI stream. by Perry R. Cook, 1995 - 2002. */ /*********************************************************/ /***** MIDI COMPATIBLE MESSAGES *****/ /***** Status Bytes Have Channel=0 **/ #define NOPE -32767 #define YEP 1 #define SK_DBL -32766 #define SK_INT -32765 #define SK_STR -32764 #define __SK_NoteOff_ 128 #define __SK_NoteOn_ 144 #define __SK_PolyPressure_ 160 #define __SK_ControlChange_ 176 #define __SK_ProgramChange_ 192 #define __SK_AfterTouch_ 208 #define __SK_ChannelPressure_ __SK_AfterTouch_ #define __SK_PitchWheel_ 224 #define __SK_PitchBend_ __SK_PitchWheel_ #define __SK_PitchChange_ 49 #define __SK_Clock_ 248 #define __SK_SongStart_ 250 #define __SK_Continue_ 251 #define __SK_SongStop_ 252 #define __SK_ActiveSensing_ 254 #define __SK_SystemReset_ 255 #define __SK_Volume_ 7 #define __SK_ModWheel_ 1 #define __SK_Modulation_ __SK_ModWheel_ #define __SK_Breath_ 2 #define __SK_FootControl_ 4 #define __SK_Portamento_ 65 #define __SK_Balance_ 8 #define __SK_Pan_ 10 #define __SK_Sustain_ 64 #define __SK_Damper_ __SK_Sustain_ #define __SK_Expression_ 11 #define __SK_AfterTouch_Cont_ 128 #define __SK_ModFrequency_ __SK_Expression_ #define __SK_ProphesyRibbon_ 16 #define __SK_ProphesyWheelUp_ 2 #define __SK_ProphesyWheelDown_ 3 #define __SK_ProphesyPedal_ 18 #define __SK_ProphesyKnob1_ 21 #define __SK_ProphesyKnob2_ 22 /*** Instrument Family Specific ***/ #define __SK_NoiseLevel_ __SK_FootControl_ #define __SK_PickPosition_ __SK_FootControl_ #define __SK_StringDamping_ __SK_Expression_ #define __SK_StringDetune_ __SK_ModWheel_ #define __SK_BodySize_ __SK_Breath_ #define __SK_BowPressure_ __SK_Breath_ #define __SK_BowPosition_ __SK_PickPosition_ #define __SK_BowBeta_ __SK_BowPosition_ #define __SK_ReedStiffness_ __SK_Breath_ #define __SK_ReedRestPos_ __SK_FootControl_ #define __SK_FluteEmbouchure_ __SK_Breath_ #define __SK_JetDelay_ __SK_FluteEmbouchure_ #define __SK_LipTension_ __SK_Breath_ #define __SK_SlideLength_ __SK_FootControl_ #define __SK_StrikePosition_ __SK_PickPosition_ #define __SK_StickHardness_ __SK_Breath_ #define __SK_TrillDepth_ 1051 #define __SK_TrillSpeed_ 1052 #define __SK_StrumSpeed_ __SK_TrillSpeed_ #define __SK_RollSpeed_ __SK_TrillSpeed_ #define __SK_FilterQ_ __SK_Breath_ #define __SK_FilterFreq_ 1062 #define __SK_FilterSweepRate_ __SK_FootControl_ #define __SK_ShakerInst_ 1071 #define __SK_ShakerEnergy_ __SK_Breath_ #define __SK_ShakerDamping_ __SK_ModFrequency_ #define __SK_ShakerNumObjects_ __SK_FootControl_ #define __SK_Strumming_ 1090 #define __SK_NotStrumming_ 1091 #define __SK_Trilling_ 1092 #define __SK_NotTrilling_ 1093 #define __SK_Rolling_ __SK_Strumming_ #define __SK_NotRolling_ __SK_NotStrumming_ #define __SK_PlayerSkill_ 2001 #define __SK_Chord_ 2002 #define __SK_ChordOff_ 2003 #define __SK_SINGER_FilePath_ 3000 #define __SK_SINGER_Frequency_ 3001 #define __SK_SINGER_NoteName_ 3002 #define __SK_SINGER_Shape_ 3003 #define __SK_SINGER_Glot_ 3004 #define __SK_SINGER_VoicedUnVoiced_ 3005 #define __SK_SINGER_Synthesize_ 3006 #define __SK_SINGER_Silence_ 3007 #define __SK_SINGER_VibratoAmt_ __SK_ModWheel_ #define __SK_SINGER_RndVibAmt_ 3008 #define __SK_SINGER_VibFreq_ __SK_Expression_ #define __SK_MaxMsgTypes_ 128 #endif chuck-1.2.0.8.dfsg/src/ugen_xxx.cpp0000644000175000017500000037342110600421721015510 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_xxx.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Spring 2004 // Summer 2005 - updated //----------------------------------------------------------------------------- #include #include #include #include #include #include #if defined(__CK_SNDFILE_NATIVE__) #include #else #include "util_sndfile.h" #endif #include "ugen_xxx.h" #include "chuck_type.h" #include "chuck_ugen.h" #include "chuck_vm.h" #include "chuck_globals.h" #include using namespace std; // LiSa query DLL_QUERY lisa_query( Chuck_DL_Query * query ); t_CKUINT g_srate; // offset static t_CKUINT stereo_offset_left = 0; static t_CKUINT stereo_offset_right = 0; static t_CKUINT stereo_offset_pan = 0; static t_CKUINT cnoise_offset_data = 0; static t_CKUINT impulse_offset_data = 0; static t_CKUINT step_offset_data = 0; static t_CKUINT zerox_offset_data = 0; static t_CKUINT delayp_offset_data = 0; static t_CKUINT sndbuf_offset_data = 0; static t_CKUINT dyno_offset_data = 0; Chuck_Type * g_t_dac = NULL; Chuck_Type * g_t_adc = NULL; //----------------------------------------------------------------------------- // name: xxx_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY xxx_query( Chuck_DL_Query * QUERY ) { g_srate = QUERY->srate; // get the env Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; // deprecate type_engine_register_deprecate( env, "dac", "DAC" ); type_engine_register_deprecate( env, "adc", "ADC" ); type_engine_register_deprecate( env, "pan2", "Pan2" ); type_engine_register_deprecate( env, "mix2", "Mix2" ); type_engine_register_deprecate( env, "gain", "Gain" ); type_engine_register_deprecate( env, "noise", "Noise" ); type_engine_register_deprecate( env, "cnoise", "CNoise" ); type_engine_register_deprecate( env, "impulse", "Impulse" ); type_engine_register_deprecate( env, "step", "Step" ); type_engine_register_deprecate( env, "halfrect", "HalfRect" ); type_engine_register_deprecate( env, "fullrect", "FullRect" ); type_engine_register_deprecate( env, "zerox", "ZeroX" ); type_engine_register_deprecate( env, "delayp", "DelayP" ); type_engine_register_deprecate( env, "sndbuf", "SndBuf" ); //! \section audio output //------------------------------------------------------------------------- // init as base class: UGen_Multi //------------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "UGen_Multi", "UGen", env->global(), multi_ctor, NULL, NULL, 0, 0 ) ) return FALSE; // add chan func = make_new_mfun( "UGen", "chan", multi_cget_chan ); func->add_arg( "int", "which" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add pan /* func = make_new_mfun( "float", "pan", multi_ctrl_pan ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pan", multi_cget_pan ); if( !type_engine_import_mfun( env, func ) ) goto error; */ //--------------------------------------------------------------------- // init as base class: UGen_Stereo //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "UGen_Stereo", "UGen_Multi", env->global(), stereo_ctor, NULL, NULL, NULL, 2, 2 ) ) return FALSE; // add left stereo_offset_left = type_engine_import_mvar( env, "UGen", "left", FALSE ); if( stereo_offset_left == CK_INVALID_OFFSET ) goto error; // add right stereo_offset_right = type_engine_import_mvar( env, "UGen", "right", FALSE ); if( stereo_offset_right == CK_INVALID_OFFSET ) goto error; // add pan stereo_offset_pan = type_engine_import_mvar( env, "float", "@pan", FALSE ); if( stereo_offset_pan == CK_INVALID_OFFSET ) goto error; // add pan func = make_new_mfun( "float", "pan", stereo_ctrl_pan ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "pan", stereo_cget_pan ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add dac //! digital/analog converter //! abstraction for underlying audio output device //--------------------------------------------------------------------- // init as base class: dac //--------------------------------------------------------------------- if( !(g_t_dac = type_engine_import_ugen_begin( env, "DAC", "UGen_Stereo", env->global(), NULL, NULL, NULL, NULL, 2, 2 )) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add adc //! analog/digital converter //! abstraction for underlying audio input device //--------------------------------------------------------------------- // init as base class: adc //--------------------------------------------------------------------- if( !(g_t_adc = type_engine_import_ugen_begin( env, "ADC", "UGen_Stereo", env->global(), NULL, NULL, NULL, NULL, 0, 2 )) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //--------------------------------------------------------------------- // init as base class: pan2 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Pan2", "UGen_Stereo", env->global(), NULL, NULL, NULL, NULL, 2, 2 ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //--------------------------------------------------------------------- // init as base class: mix2 //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Mix2", "UGen_Stereo", env->global(), NULL, NULL, NULL, NULL, 2, 2 ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add blackhole //! sample rate sample sucker //! ( like dac, ticks ugens, but no more ) //! see \example pwm.ck //QUERY->ugen_add( QUERY, "blackhole", NULL ); // set funcs //QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL ); // add bunghole //! sample rate sample sucker //! ( like dac, ticks ugens, but no more ) //QUERY->ugen_add( QUERY, "bunghole", NULL ); // set funcs //QUERY->ugen_func( QUERY, NULL, NULL, bunghole_tick, NULL ); // add gain //! gain control //! (NOTE - all unit generators can themselves change their gain) //! (this is a way to add N outputs together and scale them) //! used in \example i-robot.ck //--------------------------------------------------------------------- // init as base class: gain //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Gain", "UGen", env->global(), NULL, NULL, NULL, NULL ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; /*! \example noise n => gain g => dac; sinosc s => g; .3 => g.gain; while( true ) { 100::ms => now; } */ //! \section wave forms // add noise //! white noise generator //! see \example noise.ck \example powerup.ck //--------------------------------------------------------------------- // init as base class: noise //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Noise", "UGen", env->global(), NULL, NULL, noise_tick, NULL ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //zzz // add cnoise /*QUERY->ugen_add( QUERY, "cnoise", NULL ); QUERY->ugen_func( QUERY, cnoise_ctor, cnoise_dtor, cnoise_tick, NULL ); QUERY->ugen_ctrl( QUERY, cnoise_ctrl_mode, NULL, "string", "mode" ); QUERY->ugen_ctrl( QUERY, cnoise_ctrl_fprob, NULL, "float", "fprob" );*/ //--------------------------------------------------------------------- // init as base class: cnoise //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "CNoise", "UGen", env->global(), cnoise_ctor, cnoise_dtor, cnoise_tick, NULL ) ) return FALSE; // add member variable cnoise_offset_data = type_engine_import_mvar( env, "int", "@cnoise_data", FALSE ); if( cnoise_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: mode func = make_new_mfun( "string", "mode", cnoise_ctrl_mode ); func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: mode //func = make_new_mfun( "string", "mode", cnoise_cget_mode ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: fprob func = make_new_mfun( "float", "fprob", cnoise_ctrl_fprob ); func->add_arg( "float", "fprob" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: fprob //func = make_new_mfun( "float", "fprob", cnoise_cget_fprob ); //if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add impulse //! pulse generator - can set the value of the current sample //! default for each sample is 0 if not set //QUERY->ugen_add( QUERY, "impulse", NULL ); // set funcs //QUERY->ugen_func( QUERY, impulse_ctor, impulse_dtor, impulse_tick, NULL ); // ctrl func //QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "value" ); //QUERY->ugen_ctrl( QUERY, impulse_ctrl_value, impulse_cget_value, "float", "next" ); //! set value of next sample /*! \example impulse i => dac; while( true ) { 1.0 => i.next; 100::ms => now; } */ //--------------------------------------------------------------------- // init as base class: impulse //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Impulse", "UGen", env->global(), impulse_ctor, impulse_dtor, impulse_tick, NULL ) ) return FALSE; // add ctrl: value //func = make_new_mfun( "float", "value", impulse_ctrl_value ); //func->add_arg( "float", "value" ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: value //func = make_new_mfun( "float", "value", impulse_cget_value ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable impulse_offset_data = type_engine_import_mvar( env, "int", "@impulse_data", FALSE ); if( impulse_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: next func = make_new_mfun( "float", "next", impulse_ctrl_next ); func->add_arg( "float", "next" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: next func = make_new_mfun( "float", "next", impulse_cget_next ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add step //! step generator - like impulse, but once a value is set, //! it is held for all following samples, until value is set again //! see \example step.ck //QUERY->ugen_add( QUERY, "step", NULL ); // set funcs //QUERY->ugen_func( QUERY, step_ctor, step_dtor, step_tick, NULL ); // ctrl func //QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "value" ); //QUERY->ugen_ctrl( QUERY, step_ctrl_value, step_cget_value, "float", "next" ); //! set the step value /*! \example step s => dac; -1.0 => float amp; // square wave using step while( true ) { -amp => amp => s.next; 800::samp => now; } */ //--------------------------------------------------------------------- // init as base class: step //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Step", "UGen", env->global(), step_ctor, step_dtor, step_tick, NULL ) ) return FALSE; // add ctrl: value //func = make_new_mfun( "float", "value", step_ctrl_value ); //func->add_arg( "float", "value" ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: value //func = make_new_mfun( "float", "value", step_cget_value ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add member variable step_offset_data = type_engine_import_mvar( env, "int", "@step_data", FALSE ); if( step_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: next func = make_new_mfun( "float", "next", step_ctrl_next ); func->add_arg( "float", "next" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: next func = make_new_mfun( "float", "next", step_cget_next ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add halfrect //! half wave rectifier //! for half-wave rectification. //QUERY->ugen_add( QUERY, "halfrect", NULL ); // set funcs //QUERY->ugen_func( QUERY, NULL, NULL, halfrect_tick, NULL ); //--------------------------------------------------------------------- // init as base class: halfrect //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "HalfRect", "UGen", env->global(), NULL, NULL, halfrect_tick, NULL ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add fullrect //! full wave rectifier //QUERY->ugen_add( QUERY, "fullrect", NULL ); // set funcs //QUERY->ugen_func( QUERY, NULL, NULL, fullrect_tick, NULL ); //--------------------------------------------------------------------- // init as base class: fullrect //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "FullRect", "UGen", env->global(), NULL, NULL, fullrect_tick, NULL ) ) return FALSE; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // add zerox //! zero crossing detector //! emits a single pulse at the the zero crossing in the direction of the zero crossing. //! (see \example zerox.ck) //QUERY->ugen_add( QUERY, "zerox", NULL ); // set funcs //QUERY->ugen_func( QUERY, zerox_ctor, zerox_dtor, zerox_tick, NULL ); //--------------------------------------------------------------------- // init as base class: zerox //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "ZeroX", "UGen", env->global(), zerox_ctor, zerox_dtor, zerox_tick, NULL ) ) return FALSE; // add member variable zerox_offset_data = type_engine_import_mvar( env, "int", "@zerox_data", FALSE ); if( zerox_offset_data == CK_INVALID_OFFSET ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //! \section delay lines //! delay with varying write position ( instead of read position ) //! change to delay length will not affect the delay of samples already in //! the buffer. //! see \example delayp.ck //QUERY->ugen_add( QUERY, "delayp" , NULL); //QUERY->ugen_func ( QUERY, delayp_ctor, delayp_dtor, delayp_tick, delayp_pmsg); //QUERY->ugen_ctrl( QUERY, delayp_ctrl_delay, delayp_cget_delay , "dur", "delay" ); //! delay before subsequent values emerge //QUERY->ugen_ctrl( QUERY, delayp_ctrl_window, delayp_cget_window , "dur", "window" ); //! time for 'write head' to move //QUERY->ugen_ctrl( QUERY, delayp_ctrl_max, delayp_cget_max , "dur", "max" ); //! max delay possible. trashes buffer, so do it first! //--------------------------------------------------------------------- // init as base class: delayp //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "DelayP", "UGen", env->global(), delayp_ctor, delayp_dtor, delayp_tick, delayp_pmsg ) ) return FALSE; // add member variable delayp_offset_data = type_engine_import_mvar( env, "int", "@delayp_data", FALSE ); if( delayp_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: delay func = make_new_mfun( "dur", "delay", delayp_ctrl_delay ); func->add_arg( "dur", "delay" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: delay func = make_new_mfun( "dur", "delay", delayp_cget_delay ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: window func = make_new_mfun( "dur", "window", delayp_ctrl_window ); func->add_arg( "dur", "window" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: window func = make_new_mfun( "dur", "window", delayp_cget_window ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: max func = make_new_mfun( "dur", "max", delayp_ctrl_max ); func->add_arg( "dur", "max" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: max func = make_new_mfun( "dur", "max", delayp_cget_max ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //! \section sound files // add sndbuf //! sound buffer ( now interpolating ) //! reads from a variety of file formats //! see \example sndbuf.ck //QUERY->ugen_add( QUERY, "sndbuf", NULL ); // set funcs //QUERY->ugen_func( QUERY, sndbuf_ctor, sndbuf_dtor, sndbuf_tick, NULL ); // set ctrl //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_read, NULL, "string", "read" ); //! loads file for reading //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_write, NULL, "string", "write" ); //! loads a file for writing ( or not ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_pos, sndbuf_cget_pos, "int", "pos" ); //! set position ( 0 < p < .samples ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_loop, sndbuf_cget_loop, "int", "loop" ); //! toggle looping //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_interp, sndbuf_cget_interp, "int", "interp" ); //! set interpolation ( 0=drop, 1=linear, 2=sinc ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "rate" ); //! playback rate ( relative to file's natural speed ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_rate, sndbuf_cget_rate, "float", "play" ); //! play (same as rate) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_freq, sndbuf_cget_freq, "float", "freq" ); //! playback rate ( file loops / second ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase, sndbuf_cget_phase, "float", "phase" ); //! set phase position ( 0-1 ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_channel, sndbuf_cget_channel, "int", "channel" ); //! select channel ( 0 < p < .channels ) //QUERY->ugen_ctrl( QUERY, sndbuf_ctrl_phase_offset, sndbuf_cget_phase, "float", "phase_offset" ); //! set a phase offset //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_samples, "int", "samples" ); //! fetch number of samples //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_length, "dur", "length" ); //! fetch length //QUERY->ugen_ctrl( QUERY, NULL, sndbuf_cget_channels, "int", "channels" ); //! fetch number of channels //--------------------------------------------------------------------- // init as base class: sndbuf //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "SndBuf", "UGen", env->global(), sndbuf_ctor, sndbuf_dtor, sndbuf_tick, NULL ) ) return FALSE; // add member variable sndbuf_offset_data = type_engine_import_mvar( env, "int", "@sndbuf_data", FALSE ); if( sndbuf_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: read func = make_new_mfun( "string", "read", sndbuf_ctrl_read ); func->add_arg( "string", "read" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: read // area //func = make_new_mfun( "string", "read", sndbuf_cget_read ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: write func = make_new_mfun( "string", "write", sndbuf_ctrl_write ); func->add_arg( "string", "read" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: write //func = make_new_mfun( "string", "write", sndbuf_cget_write ); //if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: pos func = make_new_mfun( "int", "pos", sndbuf_ctrl_pos ); func->add_arg( "int", "pos" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: pos func = make_new_mfun( "int", "pos", sndbuf_cget_pos ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: loop func = make_new_mfun( "int", "loop", sndbuf_ctrl_loop ); func->add_arg( "int", "loop" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: loop func = make_new_mfun( "int", "loop", sndbuf_cget_loop ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: interp func = make_new_mfun( "int", "interp", sndbuf_ctrl_interp ); func->add_arg( "int", "interp" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: interp func = make_new_mfun( "int", "interp", sndbuf_cget_interp ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: rate func = make_new_mfun( "float", "rate", sndbuf_ctrl_rate ); func->add_arg( "float", "rate" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: rate func = make_new_mfun( "float", "rate", sndbuf_cget_rate ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: play func = make_new_mfun( "float", "play", sndbuf_ctrl_rate ); func->add_arg( "float", "play" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: play // good func = make_new_mfun( "float", "play", sndbuf_cget_rate ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: freq func = make_new_mfun( "float", "freq", sndbuf_ctrl_freq ); func->add_arg( "float", "freq" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: freq func = make_new_mfun( "float", "freq", sndbuf_cget_freq ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: phase func = make_new_mfun( "float", "phase", sndbuf_ctrl_phase ); func->add_arg( "float", "phase" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: phase func = make_new_mfun( "float", "phase", sndbuf_cget_phase ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: channel func = make_new_mfun( "int", "channel", sndbuf_ctrl_channel ); func->add_arg( "int", "channel" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: channel func = make_new_mfun( "int", "channel", sndbuf_cget_channel ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: phase_offset func = make_new_mfun( "float", "phaseOffset", sndbuf_ctrl_phase_offset ); func->add_arg( "float", "value" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: phase_offset // func = make_new_mfun( "float", "phaseOffset", sndbuf_cget_phase_offset ); // if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: chunks func = make_new_mfun( "int", "chunks", sndbuf_ctrl_chunks ); func->add_arg( "int", "frames" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: chunks func = make_new_mfun( "int", "chunks", sndbuf_cget_chunks ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: samples func = make_new_mfun( "int", "samples", sndbuf_cget_samples ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: length func = make_new_mfun( "dur", "length", sndbuf_cget_length ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: channels func = make_new_mfun( "int", "channels", sndbuf_cget_channels ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: valueAt func = make_new_mfun( "float", "valueAt", sndbuf_cget_valueAt ); func->add_arg( "int", "pos" ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; //--------------------------------------------------------------------- // init as base class: Dyno //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "Dyno", "UGen", env->global(), dyno_ctor, dyno_dtor, dyno_tick, NULL ) ) return FALSE; // add member variable dyno_offset_data = type_engine_import_mvar( env, "int", "@dyno_data", FALSE ); if( dyno_offset_data == CK_INVALID_OFFSET ) goto error; // add ctrl: limit func = make_new_mfun( "void", "limit", dyno_ctrl_limit ); //func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: compress func = make_new_mfun( "void", "compress", dyno_ctrl_compress ); //func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: gate func = make_new_mfun( "void", "gate", dyno_ctrl_gate ); //func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: expand func = make_new_mfun( "void", "expand", dyno_ctrl_expand ); //func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ctrl: duck func = make_new_mfun( "void", "duck", dyno_ctrl_duck ); //func->add_arg( "string", "mode" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: thresh func = make_new_mfun( "float", "thresh", dyno_ctrl_thresh ); func->add_arg( "float", "thresh" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add cget: thresh func = make_new_mfun( "float", "thresh", dyno_cget_thresh ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: attackTime func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime ); func->add_arg( "dur", "aTime" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: attackTime func = make_new_mfun( "dur", "attackTime", dyno_ctrl_attackTime ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: releaseTime func = make_new_mfun( "dur", "releaseTime", dyno_ctrl_releaseTime ); func->add_arg( "dur", "rTime" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: releaseTime func = make_new_mfun( "dur", "releaseTime", dyno_ctrl_releaseTime ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: ratio func = make_new_mfun( "float", "ratio", dyno_ctrl_ratio ); func->add_arg( "float", "ratio" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: ratio func = make_new_mfun( "float", "ratio", dyno_cget_ratio ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: slopeBelow func = make_new_mfun( "float", "slopeBelow", dyno_ctrl_slopeBelow ); func->add_arg( "float", "slopeBelow" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: slopeBelow func = make_new_mfun( "float", "slopeBelow", dyno_cget_slopeBelow ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: slopeAbove func = make_new_mfun( "float", "slopeAbove", dyno_ctrl_slopeAbove ); func->add_arg( "float", "slopeAbove" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: slopeAbove func = make_new_mfun( "float", "slopeAbove", dyno_cget_slopeAbove ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: sideInput func = make_new_mfun( "float", "sideInput", dyno_ctrl_sideInput ); func->add_arg( "float", "sideInput" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: sideInput func = make_new_mfun( "float", "sideInput", dyno_cget_sideInput ); if( !type_engine_import_mfun( env, func ) ) goto error; //add ctrl: externalSideInput func = make_new_mfun( "int", "externalSideInput", dyno_ctrl_externalSideInput ); func->add_arg( "int", "externalSideInput" ); if( !type_engine_import_mfun( env, func ) ) goto error; //add cget: externalSideInput func = make_new_mfun( "int", "externalSideInput", dyno_cget_externalSideInput ); if( !type_engine_import_mfun( env, func ) ) goto error; // end import if( !type_engine_import_class_end( env ) ) return FALSE; // import LiSa! if( !lisa_query( QUERY ) ) return FALSE; return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } // LiSa (live sampling data offset) static t_CKUINT LiSaBasic_offset_data = 0; static t_CKUINT LiSaMulti_offset_data = 0; //----------------------------------------------------------------------------- // name: lisa_query() // desc: ... //----------------------------------------------------------------------------- DLL_QUERY lisa_query( Chuck_DL_Query * QUERY ) { Chuck_Env * env = Chuck_Env::instance(); Chuck_DL_Func * func = NULL; //--------------------------------------------------------------------- // init class: LiSa; overloaded class for both LiSaBasic and LiSaMulti // - probably don't need the others anymore.... // author: Dan Trueman (dan /at/ music.princeton.edu) //--------------------------------------------------------------------- if( !type_engine_import_ugen_begin( env, "LiSa", "UGen", env->global(), LiSaMulti_ctor, LiSaMulti_dtor, LiSaMulti_tick, LiSaMulti_pmsg ) ) return FALSE; // set buffer size func = make_new_mfun( "dur", "duration", LiSaMulti_size ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; // start/stop recording func = make_new_mfun( "int", "record", LiSaMulti_start_record ); func->add_arg( "int", "toggle" ); if( !type_engine_import_mfun( env, func ) ) goto error; // start/stop playing func = make_new_mfun( "int", "play", LiSaMulti_start_play ); func->add_arg( "int", "voice" ); func->add_arg( "int", "toggle" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "play", LiSaMulti_start_play0 ); func->add_arg( "int", "toggle" ); if( !type_engine_import_mfun( env, func ) ) goto error; // set playback rate func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate ); func->add_arg( "int", "voice" ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "rate", LiSaMulti_ctrl_rate0 ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; // playback position func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex ); func->add_arg( "int", "voice" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "playPos", LiSaMulti_ctrl_pindex0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "playPos", LiSaMulti_cget_pindex0 ); if( !type_engine_import_mfun( env, func ) ) goto error; // record position func = make_new_mfun( "dur", "recPos", LiSaMulti_ctrl_rindex ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "recPos", LiSaMulti_cget_rindex ); if( !type_engine_import_mfun( env, func ) ) goto error; // loopstart position func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart ); func->add_arg( "int", "voice" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopStart", LiSaMulti_ctrl_lstart0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopStart", LiSaMulti_cget_lstart0 ); if( !type_engine_import_mfun( env, func ) ) goto error; // loopend position func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend); func->add_arg( "int", "voice" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopEnd", LiSaMulti_ctrl_lend0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopEnd", LiSaMulti_cget_lend0); if( !type_engine_import_mfun( env, func ) ) goto error; // loop func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop ); func->add_arg( "int", "voice" ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop); func->add_arg( "int", "voice" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "loop", LiSaMulti_ctrl_loop0 ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "loop", LiSaMulti_cget_loop0); if( !type_engine_import_mfun( env, func ) ) goto error; // bidirectional looping func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi ); func->add_arg( "int", "voice" ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi); func->add_arg( "int", "voice" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "bi", LiSaMulti_ctrl_bi0 ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "bi", LiSaMulti_cget_bi0); if( !type_engine_import_mfun( env, func ) ) goto error; // loopend_rec position func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_ctrl_loop_end_rec ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "loopEndRec", LiSaMulti_cget_loop_end_rec); if( !type_engine_import_mfun( env, func ) ) goto error; // set record feedback coefficient func = make_new_mfun( "float", "feedback", LiSaMulti_ctrl_coeff ); func->add_arg( "float", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "float", "feedback", LiSaMulti_cget_coeff); if( !type_engine_import_mfun( env, func ) ) goto error; // clear buffer func = make_new_mfun( "void", "clear", LiSaMulti_ctrl_clear ); if( !type_engine_import_mfun( env, func ) ) goto error; // get free voice func = make_new_mfun( "int", "getVoice", LiSaMulti_cget_voice ); if( !type_engine_import_mfun( env, func ) ) goto error; // set maxvoices func = make_new_mfun( "int", "maxVoices", LiSaMulti_ctrl_maxvoices ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "maxVoices", LiSaMulti_cget_maxvoices); if( !type_engine_import_mfun( env, func ) ) goto error; // ramp stuff func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "rampDown", LiSaMulti_ctrl_rampdown ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "recRamp", LiSaMulti_ctrl_rec_ramplen ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "rampUp", LiSaMulti_ctrl_rampup0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "void", "rampDown", LiSaMulti_ctrl_rampdown0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; // get value func = make_new_mfun( "dur", "value", LiSaMulti_cget_value ); func->add_arg( "int", "voice" ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "dur", "value", LiSaMulti_cget_value0 ); func->add_arg( "dur", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; // track func = make_new_mfun( "int", "track", LiSaMulti_ctrl_track ); func->add_arg( "int", "val" ); if( !type_engine_import_mfun( env, func ) ) goto error; func = make_new_mfun( "int", "track", LiSaMulti_cget_track); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); return TRUE; error: // end the class import type_engine_import_class_end( env ); return FALSE; } //----------------------------------------------------------------------------- // name: multi_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( multi_ctor ) { // do nothing } //----------------------------------------------------------------------------- // name: multi_cget_chan() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CGET( multi_cget_chan ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // value t_CKINT index = GET_NEXT_INT( ARGS ); // return RETURN->v_object = index >= 0 && index < ugen->m_multi_chan_size ? ugen->m_multi_chan[index] : NULL ; } //----------------------------------------------------------------------------- // name: stereo_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( stereo_ctor ) { // get ugen Chuck_UGen * ugen = (Chuck_UGen *)SELF; // multi if( ugen->m_multi_chan_size ) { // set left OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)(ugen->m_multi_chan[0]); // set right OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)(ugen->m_multi_chan[1]); } else // mono { // set left and right to self OBJ_MEMBER_UINT(SELF, stereo_offset_left) = (t_CKUINT)ugen; OBJ_MEMBER_UINT(SELF, stereo_offset_right) = (t_CKUINT)ugen; } } //----------------------------------------------------------------------------- // name: stereo_ctrl_pan() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTRL( stereo_ctrl_pan ) { Chuck_UGen * ugen = (Chuck_UGen * )SELF; Chuck_UGen * left = ugen->m_multi_chan[0]; Chuck_UGen * right = ugen->m_multi_chan[1]; // get arg t_CKFLOAT pan = GET_CK_FLOAT(ARGS); // clip it if( pan < -1.0 ) pan = -1.0; else if( pan > 1.0 ) pan = 1.0; // set it OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan) = pan; // pan it left->m_pan = pan < 0.0 ? 1.0 : 1.0 - pan; right->m_pan = pan > 0.0 ? 1.0 : 1.0 + pan; RETURN->v_float = pan; } //----------------------------------------------------------------------------- // name: stereo_cget_pan() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CGET( stereo_cget_pan ) { RETURN->v_float = OBJ_MEMBER_FLOAT(SELF, stereo_offset_pan); } //----------------------------------------------------------------------------- // name: dac_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( dac_tick ) { *out = in; return TRUE; } //----------------------------------------------------------------------------- // name: bunghole_tick // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( bunghole_tick ) { *out = 0.0f; return 0; } //----------------------------------------------------------------------------- // name: noise_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( noise_tick ) { *out = -1.0 + 2.0 * (SAMPLE)rand() / RAND_MAX; return TRUE; } enum { NOISE_WHITE=0, NOISE_PINK, NOISE_BROWN, NOISE_FBM, NOISE_FLIP, NOISE_XOR }; class CNoise_Data { private: SAMPLE value; t_CKFLOAT fbmH; t_CKINT counter; t_CKINT * pink_array; t_CKINT pink_depth; bool pink_rand; t_CKINT rand_bits; double scale; double bias; t_CKINT last; public: CNoise_Data() { value = 0; mode = NOISE_PINK; pink_depth = 24; pink_array = NULL; counter = 1; scale = 2.0 / (double) RAND_MAX ; bias = -1.0; pink_rand = false; t_CKINT randt = RAND_MAX; rand_bits = 0; fprob = (t_CKINT)( (double)RAND_MAX * 1.0 / 32.0 ); while ( randt > 0 ) { rand_bits++; randt = randt >> 1; } // fprintf(stderr, "random bits - %d", rand_bits ); setMode ( "pink" ); } ~CNoise_Data() {} t_CKINT fprob; t_CKUINT mode; void tick( t_CKTIME now, SAMPLE * out ); void setMode(char * c); t_CKINT pink_tick( SAMPLE * out); t_CKINT brown_tick( SAMPLE * out); t_CKINT xor_tick( SAMPLE * out); t_CKINT flip_tick( SAMPLE * out); t_CKINT fbm_tick( SAMPLE * out); }; CK_DLL_CTOR( cnoise_ctor ) { OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = (t_CKUINT)new CNoise_Data; } CK_DLL_DTOR( cnoise_dtor ) { delete (CNoise_Data *)OBJ_MEMBER_UINT(SELF, cnoise_offset_data); OBJ_MEMBER_UINT(SELF, cnoise_offset_data) = 0; } CK_DLL_TICK( cnoise_tick ) { CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data); switch( d->mode ) { case NOISE_WHITE: return noise_tick(SELF,in,out,SHRED); break; case NOISE_PINK: return d->pink_tick(out); break; case NOISE_BROWN: return d->brown_tick(out); break; case NOISE_XOR: return d->xor_tick(out); break; case NOISE_FLIP: return d->flip_tick(out); break; case NOISE_FBM: return d->fbm_tick(out); break; } return TRUE; } t_CKINT CNoise_Data::pink_tick( SAMPLE * out ) { //based on Voss-McCartney if ( pink_array == NULL ) { pink_array = (t_CKINT *) malloc ( sizeof ( t_CKINT ) * pink_depth ); last = 0; for ( t_CKINT i = 0 ; i < pink_depth ; i++ ) { pink_array[i] = rand(); last += pink_array[i]; } scale = 2.0 / ((double)RAND_MAX * ( pink_depth + 1.0 ) ); bias = 0.0; // fprintf( stderr, "scale %f %f %d %d \n", scale, bias, RAND_MAX, pink_depth + 1 ); } t_CKINT pind = 0; //count trailing zeroes while ( pind < pink_depth && ! (counter & ( 1 << pind ) ) ) pind++; // fprintf (stderr, "counter %d pink - %d \n", counter, pind ); if ( pind < pink_depth ) { t_CKINT diff = rand() - pink_array[pind]; pink_array[pind] += diff; last += diff; } *out = bias + scale * ( rand() + last ); counter++; if ( pink_rand ) counter = rand(); return TRUE; } t_CKINT CNoise_Data::xor_tick( SAMPLE * out ) { t_CKINT mask = 0; for ( t_CKINT i = 0; i < rand_bits ; i++ ) if ( rand() <= fprob ) mask |= ( 1 << i ); last = last ^ mask; *out = bias + scale * (SAMPLE)last; return TRUE; } t_CKINT CNoise_Data::flip_tick( SAMPLE * out ) { t_CKINT ind = (t_CKINT) ( (double) rand_bits * rand() / ( RAND_MAX + 1.0 ) ); last = last ^ ( 1 << ind ); // fprintf ( stderr, "ind - %d %d %f %f", ind, last, bias, scale ); *out = bias + scale * (SAMPLE)last; return TRUE; } t_CKINT CNoise_Data::brown_tick( SAMPLE * out ) { //brownian noise function..later! *out = 0; return TRUE; } t_CKINT CNoise_Data::fbm_tick( SAMPLE * out ) { //non-brownian noise function..later! *out = 0; return TRUE; } void CNoise_Data::setMode( char * c ) { if ( strcmp ( c, "white" ) == 0 ) { // fprintf(stderr, "white noise\n"); mode = NOISE_WHITE; scale = 2.0 / (t_CKFLOAT)RAND_MAX; bias = -1.0; } if ( strcmp ( c, "pink" ) == 0 ) { // fprintf(stderr, "pink noise\n"); mode = NOISE_PINK; scale = 2.0 / (double)(RAND_MAX * ( pink_depth + 1 ) ); bias = -1.0; } if ( strcmp ( c, "flip" ) == 0) { // fprintf(stderr, "bitflip noise\n"); mode = NOISE_FLIP; scale = 2.0 / (t_CKFLOAT)RAND_MAX; bias = -1.0; } if ( strcmp ( c, "xor" ) == 0) { // fprintf(stderr, "xor noise\n"); mode = NOISE_XOR; scale = 2.0 / (t_CKFLOAT)RAND_MAX; bias = -1.0; } if ( strcmp ( c, "brown" ) == 0) { // fprintf(stderr, "brownian noise\n"); mode = NOISE_BROWN; scale = 2.0 / (t_CKFLOAT)RAND_MAX; bias = -1.0; } if ( strcmp ( c, "fbm" ) == 0) { // fprintf(stderr, "fbm noise\n"); mode = NOISE_FBM; scale = 2.0 / (t_CKFLOAT)RAND_MAX; bias = -1.0; } } CK_DLL_CTRL( cnoise_ctrl_mode ) { CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data); char * mode= *(char **)GET_CK_STRING(ARGS); d->setMode(mode); } CK_DLL_CTRL( cnoise_ctrl_fprob ) { CNoise_Data * d = ( CNoise_Data * )OBJ_MEMBER_UINT(SELF, cnoise_offset_data); t_CKFLOAT p= GET_CK_FLOAT(ARGS); d->fprob = (t_CKINT) ( (double)RAND_MAX * p ); } //----------------------------------------------------------------------------- // name: struct Pulse_Data // desc: ... //----------------------------------------------------------------------------- struct Pulse_Data { SAMPLE value; t_CKUINT when; Pulse_Data( ) { value = 1.0f; when = 0; } }; //----------------------------------------------------------------------------- // name: impulse_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( impulse_ctor ) { // return data to be used later OBJ_MEMBER_UINT(SELF, impulse_offset_data) = (t_CKUINT)new Pulse_Data; } //----------------------------------------------------------------------------- // name: impulse_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( impulse_dtor ) { // delete delete (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data); OBJ_MEMBER_UINT(SELF, impulse_offset_data) = 0; } //----------------------------------------------------------------------------- // name: impulse_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( impulse_tick ) { Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data); if( d->when ) { *out = d->value; d->when = 0; } else *out = 0.0f; return TRUE; } //----------------------------------------------------------------------------- // name: impulse_ctrl_next() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTRL( impulse_ctrl_next ) { Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data); d->value = (SAMPLE)GET_CK_FLOAT(ARGS); d->when = 1; RETURN->v_float = (t_CKFLOAT)d->value; } //----------------------------------------------------------------------------- // name: impulse_cget_next() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CGET( impulse_cget_next ) { Pulse_Data * d = (Pulse_Data *)OBJ_MEMBER_UINT(SELF, impulse_offset_data); RETURN->v_float = (t_CKFLOAT)d->value; } //----------------------------------------------------------------------------- // name: step_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( step_ctor ) { // return data to be used later OBJ_MEMBER_UINT(SELF, step_offset_data) = (t_CKUINT)new SAMPLE( 1.0f ); } //----------------------------------------------------------------------------- // name: step_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( step_dtor ) { // delete delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data); OBJ_MEMBER_UINT(SELF, step_offset_data) = 0; } //----------------------------------------------------------------------------- // name: step_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( step_tick ) { SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data); *out = *d; return TRUE; } //----------------------------------------------------------------------------- // name: step_ctrl_next() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTRL( step_ctrl_next ) { SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data); *d = (SAMPLE)GET_CK_FLOAT(ARGS); RETURN->v_float = (t_CKFLOAT)(*d); } //----------------------------------------------------------------------------- // name: step_cget_next() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CGET( step_cget_next ) { SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, step_offset_data); RETURN->v_float = (t_CKFLOAT)(*d); } //----------------------------------------------------------------------------- // name: halfrect_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( halfrect_tick ) { *out = in > 0.0f ? in : 0.0f; return TRUE; } //----------------------------------------------------------------------------- // name: fullrect_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( fullrect_tick ) { *out = in >= 0.0f ? in : -in; return TRUE; } //----------------------------------------------------------------------------- // name: zerox_ctor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_CTOR( zerox_ctor ) { OBJ_MEMBER_UINT(SELF, zerox_offset_data) = (t_CKUINT)new SAMPLE( 0.0f ); } //----------------------------------------------------------------------------- // name: zerox_dtor() // desc: ... //----------------------------------------------------------------------------- CK_DLL_DTOR( zerox_dtor ) { delete (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data); OBJ_MEMBER_UINT(SELF, zerox_offset_data) = 0; } #define __SGN(x) (x >= 0.0f ? 1.0f : -1.0f ) //----------------------------------------------------------------------------- // name: zerox_tick() // desc: ... //----------------------------------------------------------------------------- CK_DLL_TICK( zerox_tick ) { SAMPLE * d = (SAMPLE *)OBJ_MEMBER_UINT(SELF, zerox_offset_data); *out = __SGN(in) != __SGN(*d); *out *= __SGN(in); *d = in; return TRUE; } struct delayp_data { SAMPLE * buffer; t_CKINT bufsize; t_CKTIME now; double readpos; //readpos ( moves at constant speed, sample per sample double writepos; // relative to read position t_CKTIME offset; // distance between read and write t_CKDUR offset_start; t_CKDUR offset_target; t_CKTIME move_end_time; //target time t_CKDUR move_duration; //time we started shift SAMPLE last_sample; t_CKDUR last_offset; #ifdef _DEBUG int lasti; #endif double acoeff[2]; double bcoeff[2]; SAMPLE outputs[3]; SAMPLE inputs[3]; delayp_data() { bufsize = 2 * g_srate; buffer = ( SAMPLE * ) realloc ( NULL, sizeof ( SAMPLE ) * bufsize ); t_CKINT i; for ( i = 0 ; i < bufsize ; i++ ) buffer[i] = 0; for ( i = 0 ; i < 3 ; i++ ) { acoeff[i] = 0; bcoeff[i] = 0; } acoeff[0] = 1.0; acoeff[1] = -.99; bcoeff[0] = 1.0; bcoeff[1] = -1.0; readpos = 0.0; now = 0.0; offset = 0.0; last_offset = 0.0; offset_start = 0.0; offset_target = 0.0; move_duration = 1.0; move_end_time = 0.0; #ifdef _DEBUG lasti = -1; #endif last_sample = 0; } ~delayp_data() { SAFE_DELETE_ARRAY( buffer ); } }; CK_DLL_CTOR( delayp_ctor ) { OBJ_MEMBER_UINT(SELF, delayp_offset_data) = (t_CKUINT)new delayp_data; } CK_DLL_DTOR( delayp_dtor ) { delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data); SAFE_DELETE(d); OBJ_MEMBER_UINT(SELF, delayp_offset_data) = 0; } CK_DLL_PMSG( delayp_pmsg ) { return TRUE; } CK_DLL_TICK( delayp_tick ) { delayp_data * d = (delayp_data *)OBJ_MEMBER_UINT(SELF, delayp_offset_data); if ( !d->buffer ) return FALSE; // area d->now = ((Chuck_UGen*)SELF)->shred->vm_ref->shreduler()->now_system; //calculate new write-offset position ( we interpolate if we've been assigned a new write-offset ) if ( d->now >= d->move_end_time || d->move_duration == 0 ) d->offset = d->offset_target; else { double dt = 1.0 + ( d->now - d->move_end_time ) / ( d->move_duration ); d->offset = d->offset_start + dt * ( d->offset_target - d->offset_start ); // fprintf (stderr, "dt %f, off %f , start %f target %f\n", dt, d->writeoff, d->writeoff_start, d->writeoff_target ); } //find locations in buffer... double write = (d->readpos ) + d->offset; double last_write = (d->readpos - 1.0) + d->last_offset ; //linear interpolation. will introduce some lowpass/aliasing. double write_delta = write - last_write; double sample_delta = in - d->last_sample; double duck_constant = 0.69; double gee = fabs(write_delta) - 1.0; if ( gee < 24.0 ) { double head_contact = ( gee > 0 ) ? exp ( - duck_constant * gee ) : 1.0; t_CKINT i, smin, smax, sampi; SAMPLE sampf = 0; if ( write_delta >= 0 ) { //forward. smin = (t_CKINT) floor ( last_write ); smax = (t_CKINT) floor ( write ); for ( i = smin+1 ; i <= smax ; i++ ) { sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta; sampi = ( i + d->bufsize * 2 ) % d->bufsize; #ifdef _DEBUG if ( d->lasti == sampi ) { fprintf( stderr, "[chuck](via Curve): over!\n"); } d->lasti = sampi; #endif d->buffer[sampi] += sampf * head_contact ; } } else { //moving in reverse smin = (t_CKINT) floor ( write ); smax = (t_CKINT) floor ( last_write ); for ( i = smin+1 ; i <= smax ; i++ ) { sampf = d->last_sample + sample_delta * ( double(i) - last_write ) / write_delta; sampi = ( i + d->bufsize * 2 ) % d->bufsize; #ifdef _DEBUG if ( d->lasti == sampi ) { fprintf(stderr, "[chuck](via Curve): over!\n"); } d->lasti = sampi; #endif d->buffer[sampi] += sampf * head_contact; } } } d->last_offset = d->offset; d->last_sample = in; //output should go through a dc blocking filter, for cases where //we are zipping around in the buffer leaving a fairly constant //trail of samples //output last sample t_CKINT rpos = (t_CKINT) fmod( d->readpos, d->bufsize ) ; // *out = d->buffer[rpos]; /* // did i try to write a dc blocking filter? d->outputs[0] = 0.0; d->inputs [0] = d->buffer[rpos]; d->outputs[0] += d->bcoeff[1] * d->inputs[1]; d->inputs [1] = d->inputs[0]; d->outputs[0] += d->bcoeff[0] * d->inputs[0]; d->outputs[0] += -d->acoeff[1] * d->outputs[1]; d->outputs[1] = d->outputs[0]; //clear at readpos ( write doesn't !) *out = d->outputs[0]; */ *out = d->buffer[rpos]; d->buffer[rpos] = 0; //clear once it's been read d->readpos = fmod ( d->readpos + 1.0 , double( d->bufsize ) ); return TRUE; } CK_DLL_CTRL( delayp_ctrl_delay ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); t_CKDUR target = GET_CK_DUR(ARGS); // rate // area if ( target != d->offset_target ) { if ( target > d->bufsize ) { fprintf( stderr, "[chuck](via delayp): delay time %f over max! set max first!\n", target); return; } d->offset_target = target; d->offset_start = d->last_offset; t_CKTIME snow = ((Chuck_UGen*)SELF)->shred->now; d->move_end_time = snow + d->move_duration; } RETURN->v_dur = d->last_offset; // TODO: } CK_DLL_CGET( delayp_cget_delay ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); //SET_NEXT_DUR( out, d->writeoff_last ); RETURN->v_dur = d->last_offset; // TODO: } CK_DLL_CTRL( delayp_ctrl_window ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); t_CKDUR window = GET_CK_DUR(ARGS); // rate if ( window >= 0 ) { d->move_duration = window; //fprintf ( stderr, "set window time %f , %f , %d \n", d->writeoff_window_time, d->writeoff, d->bufsize ); } RETURN->v_dur = d->move_duration; // TODO: } CK_DLL_CGET( delayp_cget_window ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); RETURN->v_dur = d->move_duration; // TODO: } CK_DLL_CTRL( delayp_ctrl_max ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); t_CKDUR nmax = GET_CK_DUR(ARGS); // rate if ( d->bufsize != (t_CKINT)nmax && nmax > 1.0 ) { d->bufsize = (t_CKINT)(nmax+.5); d->buffer = ( SAMPLE * ) realloc ( d->buffer, sizeof ( SAMPLE ) * d->bufsize ); for ( t_CKINT i = 0; i < d->bufsize; i++ ) d->buffer[i] = 0; } RETURN->v_dur = d->bufsize; // TODO?? } CK_DLL_CGET( delayp_cget_max ) { delayp_data * d = ( delayp_data * ) OBJ_MEMBER_UINT(SELF, delayp_offset_data); //SET_NEXT_DUR( out, (t_CKDUR) d->bufsize ); RETURN->v_dur = d->bufsize; } //----------------------------------------------------------------------------- // name: sndbuf // desc: ... //----------------------------------------------------------------------------- enum { SNDBUF_DROP = 0, SNDBUF_INTERP, SNDBUF_SINC}; #define WIDTH 16 /* this controls the number of neighboring samples which are used to interpolate the new samples. The processing time is linearly related to this width */ #define DELAY_SIZE 140 #define USE_TABLE TRUE /* this controls whether a linearly interpolated lookup table is used for sinc function calculation, or the sinc is calculated by floating point trig function calls. */ #define USE_INTERP TRUE /* this controls whether the table is linear interpolated or not. If you re not using the table, this has no effect */ #define SAMPLES_PER_ZERO_CROSSING 32 /* this defines how finely the sinc function is sampled for storage in the table */ #ifdef CK_SNDBUF_MEMORY_BUFFER //------------------------------------------------------------------------------ // name: MultiBuffer // desc: presents multiple buffers in memory as a single sequential logical // buffer, for constant time reallocing. tries to be as discreet as possible, // so you can basically use it like a pointer. optimized for iterative access, // as random access has T = O(bufsize) //------------------------------------------------------------------------------ template< class _type > class MultiBuffer { public: MultiBuffer() { m_size = 0; } ~MultiBuffer() { deallocate(); } size_t size() { return m_size; } void resize( size_t size ) { assert( size > m_size ); // for now size_t new_buffer_size = size - m_size; extent new_extent; new_extent.position = new _type[new_buffer_size]; new_extent.length = new_buffer_size; m_bufs.push_back( new_extent ); m_size = size; } void deallocate() { // delete everything size_t i, len = m_bufs.size(); for( i = 0; i < len; i++ ) delete[] m_bufs[i].position; m_size = 0; } class Pointer { public: Pointer() { m_mb = NULL; m_lpos = 0; m_extent = 0; m_extpos = 0; } Pointer( MultiBuffer * mb ) { m_mb = mb; m_lpos = 0; m_extent = 0; m_extpos = 0; } Pointer( const Pointer & mbp ) { m_mb = mbp.m_mb; m_lpos = mbp.m_lpos; m_extent = mbp.m_extent; m_extpos = mbp.m_extpos; } Pointer & operator=( MultiBuffer & mb ) { m_mb = &mb; m_lpos = 0; m_extent = 0; m_extpos = 0; return *this; } Pointer & operator=( const Pointer & mbp ) { m_mb = mbp.m_mb; m_lpos = mbp.m_lpos; m_extent = mbp.m_extent; m_extpos = mbp.m_extpos; return *this; } Pointer & operator=( size_t i ) { reset(); increment( i ); return *this; } _type & operator*() { return m_mb->m_bufs[m_extent].position[m_extpos]; } Pointer operator+( size_t i ) const { Pointer mbp( *this ); mbp.increment( i ); return mbp; } Pointer operator++( int ) { Pointer mbp = *this; this->increment( 1 ); return mbp; } bool operator>=( const Pointer & mbp ) const { return ( m_lpos >= mbp.m_lpos ); } bool operator>=( const size_t i ) const { return ( m_lpos >= i ); } void increment( size_t i ) { m_lpos += i; if( m_lpos >= (m_mb->m_size) ) { m_extent = m_mb->m_bufs.size(); m_extpos = m_lpos - m_mb->m_size; return; } extent ext_current = m_mb->m_bufs[m_extent]; i += m_extpos; while( i >= ext_current.length ) { i -= ext_current.length; m_extent++; ext_current = m_mb->m_bufs[m_extent]; } m_extpos = i; } void reset() { m_lpos = 0; m_extent = 0; m_extpos = 0; } protected: MultiBuffer * m_mb; size_t m_lpos; // position in logical buffer size_t m_extent; // current extent size_t m_extpos; // position within the extent }; protected: struct extent { _type * position; size_t length; }; /* data shared by a set of MultiBuffers */ vector< extent > m_bufs; // array of sequentially allocated buffers size_t m_size; // overall size of total memory represented }; #endif /* CK_SNDBUF_MEMORY_BUFFER */ // data for each sndbuf struct sndbuf_data { SAMPLE * buffer; t_CKUINT num_samples; t_CKUINT num_channels; t_CKUINT num_frames; t_CKUINT samplerate; t_CKUINT chan; t_CKUINT chunks; t_CKUINT chunks_read; t_CKUINT chunks_total; t_CKUINT chunks_size; bool * chunk_table; SAMPLE * eob; SAMPLE * curr; t_CKFLOAT sampleratio; t_CKFLOAT curf; t_CKFLOAT rate_factor; t_CKFLOAT rate; t_CKINT interp; t_CKBOOL loop; bool sinc_table_built; bool sinc_use_table; bool sinc_use_interp; t_CKINT sinc_samples_per_zero_crossing; t_CKINT sinc_width; double * sinc_table; #ifdef CK_SNDBUF_MEMORY_BUFFER MultiBuffer< SAMPLE > mb_buffer; t_CKUINT mb_max_samples; MultiBuffer< SAMPLE >::Pointer mb_record_position; MultiBuffer< SAMPLE >::Pointer mb_playback_position; #endif /* CK_SNDBUF_MEMORY_BUFFER */ SNDFILE * fd; // constructor sndbuf_data() { buffer = NULL; interp = SNDBUF_INTERP; num_channels = 0; num_frames = 0; num_samples = 0; chunks = 0; chunks_read = 0; chunks_total = 0; chunks_size = 0; chunk_table = NULL; samplerate = 0; sampleratio = 1.0; chan = 0; curf = 0.0; rate_factor = 1.0; rate = 1.0; eob = NULL; curr = NULL; sinc_table_built = false; sinc_use_table = USE_TABLE; sinc_use_interp = USE_INTERP; sinc_width = WIDTH; sinc_samples_per_zero_crossing = SAMPLES_PER_ZERO_CROSSING; sinc_table = NULL; #ifdef CK_SNDBUF_MEMORY_BUFFER mb_buffer = MultiBuffer< SAMPLE >(); #endif /* CK_SNDBUF_MEMORY_BUFFER */ loop = FALSE; fd = NULL; } ~sndbuf_data() { SAFE_DELETE_ARRAY( buffer ); SAFE_DELETE_ARRAY( chunk_table ); } }; double sndbuf_sinc( sndbuf_data * d, double x ); double sndbuf_t_sinc( sndbuf_data * d, double x ); void sndbuf_make_sinc( sndbuf_data * d ); void sndbuf_sinc_interpolate( sndbuf_data * d, SAMPLE * out ); CK_DLL_CTOR( sndbuf_ctor ) { OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = (t_CKUINT)new sndbuf_data; } CK_DLL_DTOR( sndbuf_dtor ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); SAFE_DELETE(d); OBJ_MEMBER_UINT(SELF, sndbuf_offset_data) = 0; } inline t_CKUINT sndbuf_read( sndbuf_data * d, t_CKUINT offset, t_CKUINT howmuch ) { // check if( d->fd == NULL ) return 0; if( offset >= d->num_frames ) return 0; // log // EM_log( CK_LOG_FINE, "(sndbuf): reading %d:%d frames...", offset, howmuch ); // prevent overflow if( howmuch > d->num_frames - offset ) howmuch = d->num_frames - offset; t_CKUINT n; // seek sf_seek( d->fd, offset, SEEK_SET ); #if defined(CK_S_DOUBLE) n = sf_readf_double( d->fd, d->buffer+offset*d->num_channels, howmuch ); #else n = sf_readf_float( d->fd, d->buffer+offset*d->num_channels, howmuch ); #endif d->chunks_read += n; // close if( d->chunks_read >= d->num_frames ) { // log EM_log( CK_LOG_INFO, "(sndbuf): all frames read, closing file..." ); sf_close( d->fd ); d->fd = NULL; } return n; } inline t_CKINT sndbuf_load( sndbuf_data * d, t_CKUINT where ) { // map to bin t_CKUINT bin = (t_CKUINT)(where / (t_CKFLOAT)d->chunks_size); if( bin >= d->chunks_total ) return 0; // already loaded if( d->chunk_table[bin] ) return 0; // read it t_CKINT ret = sndbuf_read( d, bin*d->chunks_size, d->chunks_size ); // flag it d->chunk_table[bin] = true; // log // EM_log( CK_LOG_FINER, "chunk test: pos: %d bin: %d read:%d/%d", where, bin, d->chunks_read, d->num_frames ); return ret; } inline void sndbuf_setpos( sndbuf_data *d, double pos ) { if( !d->buffer ) return; d->curf = pos; // set curf within bounds if( d->loop ) { while( d->curf >= d->num_frames ) d->curf -= d->num_frames; while( d->curf < 0 ) d->curf += d->num_frames; } else { if( d->curf < 0 ) d->curf = 0; else if( d->curf >= d->num_frames ) d->curf = d->num_frames; } t_CKINT i = (t_CKINT)d->curf; // ensure load if( d->fd != NULL ) sndbuf_load( d, i ); // sets curr to correct position ( account for channels ) d->curr = d->buffer + d->chan + i * d->num_channels; } inline SAMPLE sndbuf_sampleAt( sndbuf_data * d, t_CKINT pos ) { // boundary cases t_CKINT nf = d->num_frames; if( d->loop ) { while( pos > nf ) pos -= nf; while( pos < 0 ) pos += nf; } else { if( pos > nf ) pos = nf; if( pos < 0 ) pos = 0; } t_CKUINT index = d->chan + pos * d->num_channels; // ensure load if( d->fd != NULL ) sndbuf_load( d, pos ); // return sample return d->buffer[index]; } inline double sndbuf_getpos( sndbuf_data * d ) { if( !d->buffer ) return 0; return floor(d->curf); } CK_DLL_CTRL( sndbuf_ctrl_loop ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); d->loop = GET_CK_INT(ARGS); RETURN->v_int = d->loop; // TODO: Check (everything) } CK_DLL_CGET( sndbuf_cget_loop ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_int = d->loop; } // PRC's sinc interpolation function.. as found // http://www.cs.princeton.edu/courses/archive/spring03/cs325/src/TimeStuf/srconvrt.c // // there's probably a lot in there that could be optimized, if we care to.. // #define PI 3.14159265358979323846 // wow... we are sensitive.. inline double sndbuf_linear_interp( double * first, double * second, double * frac ); bool sinc_table_built = false; void sndbuf_sinc_interpolate( sndbuf_data *d, SAMPLE * out ) { signed long j; double factor = d->rate; double time_now = d->curf; double one_over_factor; // UNUSED: double int_time = 0; // UNUSED: double last_time = 0; double temp1 = 0.0; long time_i = (long)time_now; // bounds checking now in sampleAt function... if( factor < 1.0 ) { for( j = -d->sinc_width + 1; j < d->sinc_width; j++ ) { temp1 += sndbuf_sampleAt(d,time_i+j) * sndbuf_sinc( d, (double)j ); } *out = (SAMPLE)temp1; } else { one_over_factor = 1.0 / factor; for( j = -d->sinc_width + 1; j < d->sinc_width; j++ ) { temp1 += sndbuf_sampleAt(d,time_i+j) * one_over_factor * sndbuf_sinc( d, one_over_factor * (double)j ); } *out = (SAMPLE)temp1; } } void sndbuf_make_sinc( sndbuf_data * d ) { t_CKINT i; // fprintf(stderr, "building sinc table\n" ); double temp, win_freq, win; win_freq = ONE_PI / d->sinc_width / d->sinc_samples_per_zero_crossing; t_CKINT tabsize = d->sinc_width * d->sinc_samples_per_zero_crossing; d->sinc_table = (double *) realloc( d->sinc_table, tabsize * sizeof(double) ); d->sinc_table[0] = 1.0; for( i = 1; i < tabsize; i++ ) { temp = (double) i * ONE_PI / d->sinc_samples_per_zero_crossing; d->sinc_table[i] = (float)(sin(temp) / temp); win = 0.5 + 0.5 * cos(win_freq * i); d->sinc_table[i] *= (float)win; } d->sinc_table_built = true; } inline double sndbuf_linear_interp( double first_number, double second_number, double fraction ) { return (first_number + ((second_number - first_number) * fraction)); } double sndbuf_t_sinc( sndbuf_data * d, double x ) { t_CKINT low; double temp,delta; if( !d->sinc_table_built ) sndbuf_make_sinc(d); if( fabs(x) >= d->sinc_width-1 ) return 0.0; else { temp = fabs(x) * (double) d->sinc_samples_per_zero_crossing; low = (t_CKINT)temp; /* these are interpolation steps */ if( d->sinc_use_interp ) { delta = temp - low; /* and can be ommited if desired */ return sndbuf_linear_interp( d->sinc_table[low], d->sinc_table[low + 1], delta ); } else return d->sinc_table[low]; } } double sndbuf_sinc( sndbuf_data * d, double x ) { double temp; if( d->sinc_use_table ) return sndbuf_t_sinc(d,x); else { if( x == 0.0 ) return 1.0; else { temp = ONE_PI * x; return sin(temp) / (temp); } } } CK_DLL_TICK( sndbuf_tick ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); #ifdef CK_SNDBUF_MEMORY_BUFFER // spencer's memory buffer stuff if( d->fd == 0 ) // no file open - memory buffer mode { Chuck_UGen * ugen = (Chuck_UGen *)SELF; if( ugen->m_num_src ) // recording mode { if( d->mb_buffer.size() == 0 ) { d->mb_buffer.resize( 44100 * 4 ); // default size: 4 seconds d->mb_record_position = d->mb_buffer; d->mb_playback_position = d->mb_buffer; } if( d->mb_record_position >= d->mb_buffer.size() ) d->mb_buffer.resize( d->mb_buffer.size() * 2 ); *(d->mb_record_position++) = in; } if( d->mb_buffer.size() ) { if( d->mb_playback_position >= d->mb_record_position ) { if( d->loop ) d->mb_playback_position = 0; else if( ugen->m_num_src ) { *out = 0; return TRUE; } else return FALSE; } *out = *(d->mb_playback_position++); } return TRUE; } #endif /* CK_SNDBUF_MEMORY_BUFFER */ if( !d->buffer ) return FALSE; // we're ticking once per sample ( system ) // curf in samples; if( !d->loop && d->curr >= d->eob + d->num_channels ) return FALSE; // calculate frame if( d->interp == SNDBUF_DROP ) { *out = (SAMPLE)( (*(d->curr)) ) ; } else if( d->interp == SNDBUF_INTERP ) { // samplewise linear interp double alpha = d->curf - floor(d->curf); *out = (SAMPLE)( (*(d->curr)) ) ; *out += (float)alpha * ( sndbuf_sampleAt(d, (long)d->curf+1 ) - *out ); } else if( d->interp == SNDBUF_SINC ) { // do that fancy sinc function! sndbuf_sinc_interpolate(d, out); } // advance d->curf += d->rate; sndbuf_setpos(d, d->curf); return TRUE; } #include "util_raw.h" CK_DLL_CTRL( sndbuf_ctrl_read ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); if( d->buffer ) { delete [] d->buffer; d->buffer = NULL; } if( d->chunk_table ) { delete [] d->chunk_table; d->chunk_table = NULL; } if( d->fd ) { sf_close( d->fd ); d->fd = NULL; } // log EM_log( CK_LOG_INFO, "(sndbuf): reading '%s'...", filename ); // built in if( strstr(filename, "special:") ) { SAMPLE * rawdata = NULL; t_CKUINT rawsize = 0; t_CKUINT srate = 22050; // which if( strstr(filename, "special:sinewave") ) { rawsize = 256; rawdata = NULL; } else if( strstr(filename, "special:ahh") ) { rawsize = ahh_size; rawdata = ahh_data; } else if( strstr(filename, "special:britestk") ) { rawsize = britestk_size; rawdata = britestk_data; } else if( strstr(filename, "special:dope") ) { rawsize = dope_size; rawdata = dope_data; } else if( strstr(filename, "special:eee") ) { rawsize = eee_size; rawdata = eee_data; } else if( strstr(filename, "special:fwavblnk") ) { rawsize = fwavblnk_size; rawdata = fwavblnk_data; } else if( strstr(filename, "special:halfwave") ) { rawsize = halfwave_size; rawdata = halfwave_data; } else if( strstr(filename, "special:impuls10") ) { rawsize = impuls10_size; rawdata = impuls10_data; } else if( strstr(filename, "special:impuls20") ) { rawsize = impuls20_size; rawdata = impuls20_data; } else if( strstr(filename, "special:impuls40") ) { rawsize = impuls40_size; rawdata = impuls40_data; } else if( strstr(filename, "special:mand1") ) { rawsize = mand1_size; rawdata = mand1_data; } else if( strstr(filename, "special:mandpluk") ) { rawsize = mandpluk_size; rawdata = mandpluk_data; } else if( strstr(filename, "special:marmstk1") ) { rawsize = marmstk1_size; rawdata = marmstk1_data; } else if( strstr(filename, "special:ooo") ) { rawsize = ooo_size; rawdata = ooo_data; } else if( strstr(filename, "special:peksblnk") ) { rawsize = peksblnk_size; rawdata = peksblnk_data; } else if( strstr(filename, "special:ppksblnk") ) { rawsize = ppksblnk_size; rawdata = ppksblnk_data; } else if( strstr(filename, "special:silence") ) { rawsize = silence_size; rawdata = silence_data; } else if( strstr(filename, "special:sineblnk") ) { rawsize = sineblnk_size; rawdata = sineblnk_data; } else if( strstr(filename, "special:sinewave") ) { rawsize = sinewave_size; rawdata = sinewave_data; } else if( strstr(filename, "special:snglpeak") ) { rawsize = snglpeak_size; rawdata = snglpeak_data; } else if( strstr(filename, "special:twopeaks") ) { rawsize = twopeaks_size; rawdata = twopeaks_data; } else if( strstr(filename, "special:glot_ahh") ) { rawsize = glot_ahh_size; rawdata = glot_ahh_data; srate = 44100; } else if( strstr(filename, "special:glot_eee") ) { rawsize = glot_eee_size; rawdata = glot_eee_data; srate = 44100; } else if( strstr(filename, "special:glot_ooo") ) { rawsize = glot_ooo_size; rawdata = glot_ooo_data; srate = 44100; } else if( strstr(filename, "special:glot_pop") ) { rawsize = glot_pop_size; rawdata = glot_pop_data; srate = 44100; } d->num_frames = rawsize; d->num_channels = 1; d->chan = 0; d->samplerate = srate; d->num_samples = rawsize; // no chunking d->chunks_read = d->num_frames; if( rawdata ) { d->buffer = new SAMPLE[rawsize+1]; for( t_CKUINT j = 0; j < rawsize; j++ ) { d->buffer[j] = (SAMPLE)rawdata[j]/(SAMPLE)SHRT_MAX; } } else if( strstr(filename, "special:sinewave") ) { d->buffer = new SAMPLE[rawsize+1]; for( t_CKUINT j = 0; j < rawsize; j++ ) d->buffer[j] = sin(2*ONE_PI*j/rawsize); } else { fprintf( stderr, "[chuck](via SndBuf): cannot load '%s'\n", filename ); return; } d->buffer[rawsize] = d->buffer[0]; } else // read file { // stat the file first struct stat s; if( stat( filename, &s ) ) { fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename ); return; } // open it SF_INFO info; info.format = 0; char * format = strrchr( filename, '.'); if( format && strcmp( format, ".raw" ) == 0 ) { fprintf( stderr, "[chuck](via SndBuf) %s :: type is '.raw'...\n assuming 16 bit signed mono (PCM)\n", filename ); info.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 | SF_ENDIAN_CPU ; info.channels = 1; info.samplerate = 44100; } // open the handle d->fd = sf_open( filename, SFM_READ, &info ); t_CKINT er = sf_error( d->fd ); if( er ) { fprintf( stderr, "[chuck](via SndBuf): sndfile error '%i' opening '%s'...\n", er, filename ); fprintf( stderr, "[chuck](via SndBuf): (reason: %s)\n", sf_strerror( d->fd ) ); if( d->fd ) sf_close( d->fd ); // escape return; } // allocate t_CKINT size = info.channels * info.frames; d->buffer = new SAMPLE[size+info.channels]; memset( d->buffer, 0, (size+info.channels)*sizeof(SAMPLE) ); d->chan = 0; d->num_frames = info.frames; d->num_channels = info.channels; d->samplerate = info.samplerate; d->num_samples = size; // log EM_pushlog(); EM_log( CK_LOG_INFO, "channels: %d", d->num_channels ); EM_log( CK_LOG_INFO, "frames: %d", d->num_frames ); EM_log( CK_LOG_INFO, "srate: %d", d->samplerate ); EM_log( CK_LOG_INFO, "chunks: %d", d->chunks ); EM_poplog(); // read sf_seek( d->fd, 0, SEEK_SET ); d->chunks_read = 0; // no chunk if( !d->chunks ) { // read all t_CKUINT f = sndbuf_read( d, 0, d->num_frames ); // check if( f != (t_CKUINT)d->num_frames ) { fprintf( stderr, "[chuck](via SndBuf): read %d rather than %d frames from %s\n", f, size, filename ); sf_close( d->fd ); d->fd = NULL; return; } assert( d->fd == NULL ); } else { // reset d->chunks_size = d->chunks; d->chunks_total = d->num_frames / d->chunks; d->chunks_total += d->num_frames % d->chunks ? 1 : 0; d->chunks_read = 0; d->chunk_table = new bool[d->chunks_total]; memset( d->chunk_table, 0, d->chunks_total * sizeof(bool) ); // read chunk // sndbuf_load( d, 0 ); } } // d->interp = SNDBUF_INTERP; d->sampleratio = (double)d->samplerate / (double)g_srate; // set the rate d->rate = d->sampleratio * d->rate_factor; d->curr = d->buffer; d->curf = 0; d->eob = d->buffer + d->num_samples; } CK_DLL_CTRL( sndbuf_ctrl_write ) { #ifdef SPENCER_SNDBUF_WRITE sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); const char * filename = GET_CK_STRING(ARGS)->str.c_str(); if( d->buffer ) { delete [] d->buffer; d->buffer = NULL; } struct stat s; if( stat( filename, &s ) ) { fprintf( stderr, "[chuck](via SndBuf): cannot stat file '%s'...\n", filename ); return; } d->curr = d->buffer; d->eob = d->buffer + d->num_samples; #endif } CK_DLL_CTRL( sndbuf_ctrl_rate ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKFLOAT rate = GET_CK_FLOAT(ARGS); // rate d->rate = rate * d->sampleratio; d->rate_factor = rate; RETURN->v_float = d->rate_factor; // TODO: (or not TODO:) } CK_DLL_CGET( sndbuf_cget_rate ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_float = d->rate_factor; } CK_DLL_CTRL( sndbuf_ctrl_freq ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKFLOAT freq = GET_CK_FLOAT(ARGS); //hz d->rate = ( freq * (double) d->num_frames / (double) g_srate ); d->rate_factor = d->rate / d->sampleratio; RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames ); // TODO: really? } CK_DLL_CGET( sndbuf_cget_freq ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_float = d->rate * (t_CKFLOAT) g_srate / ( (t_CKFLOAT) d->num_frames ); } CK_DLL_CTRL( sndbuf_ctrl_phase ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKFLOAT phase = GET_CK_FLOAT(ARGS); sndbuf_setpos(d, phase * (double)d->num_frames); RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames; // TODO: } CK_DLL_CGET( sndbuf_cget_phase ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); //SET_NEXT_FLOAT( out, (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames ); RETURN->v_float = (t_CKFLOAT) d->curf / (t_CKFLOAT)d->num_frames; } CK_DLL_CTRL( sndbuf_ctrl_channel ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); unsigned long chan = (unsigned long)GET_CK_INT(ARGS); if ( chan >= 0 && chan < d->num_channels ) { d->chan = chan; } RETURN->v_int = (t_CKINT)d->chan; } CK_DLL_CGET( sndbuf_cget_channel ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); //SET_NEXT_INT( out, d->chan ); RETURN->v_int = (t_CKINT)d->chan; } CK_DLL_CTRL( sndbuf_ctrl_pos ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKINT pos = GET_CK_INT(ARGS); #ifdef CK_SNDBUF_MEMORY_BUFFER if( pos >= 0 && pos < d->mb_max_samples ) d->mb_playback_position = pos; #endif /* CK_SNDBUF_MEMORY_BUFFER */ sndbuf_setpos(d, pos); RETURN->v_int = (t_CKINT)sndbuf_getpos(d); // TODO TODO TODOOO } CK_DLL_CGET( sndbuf_cget_pos ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_int = (t_CKINT)sndbuf_getpos(d); } CK_DLL_CTRL( sndbuf_ctrl_interp ) { sndbuf_data * d = ( sndbuf_data * ) OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKINT interp = GET_CK_INT(ARGS); d->interp = interp; RETURN->v_int = d->interp; } CK_DLL_CGET( sndbuf_cget_interp ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_int = d->interp; } CK_DLL_CTRL( sndbuf_ctrl_chunks ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKINT frames = GET_NEXT_INT(ARGS); d->chunks = frames >= 0 ? frames : 0; RETURN->v_int = d->chunks; } CK_DLL_CGET( sndbuf_cget_chunks ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); RETURN->v_int = d->chunks; } CK_DLL_CTRL( sndbuf_ctrl_phase_offset ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKFLOAT phase_offset = GET_CK_FLOAT(ARGS); sndbuf_setpos(d, d->curf + phase_offset * (t_CKFLOAT)d->num_frames ); } CK_DLL_CGET( sndbuf_cget_samples ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); //SET_NEXT_INT( out, d->num_frames ); RETURN->v_int = d->num_frames; } CK_DLL_CGET( sndbuf_cget_length ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); //SET_NEXT_DUR( out, (t_CKDUR)d->num_frames ); RETURN->v_dur = (t_CKDUR)d->num_frames / d->sampleratio; } CK_DLL_CGET( sndbuf_cget_channels ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); //SET_NEXT_INT( out, d->num_channels ); RETURN->v_int = d->num_channels; } CK_DLL_CGET( sndbuf_cget_valueAt ) { sndbuf_data * d = (sndbuf_data *)OBJ_MEMBER_UINT(SELF, sndbuf_offset_data); t_CKINT i = GET_CK_INT(ARGS); if( d->fd ) sndbuf_load( d, i ); RETURN->v_float = ( i > d->num_frames || i < 0 ) ? 0 : d->buffer[i]; } class Dyno_Data { private: const static t_CKDUR ms; public: t_CKFLOAT slopeAbove; t_CKFLOAT slopeBelow; t_CKFLOAT thresh; t_CKFLOAT rt; t_CKFLOAT at; t_CKFLOAT xd; //sidechain int externalSideInput; // use input signal or a ctrl signal for env t_CKFLOAT sideInput; // the ctrl signal for the envelope int count; //diagnostic Dyno_Data() { xd = 0.0; count = 0; sideInput = 0; limit(); } ~Dyno_Data() {} void limit(); void compress(); void gate(); void expand(); void duck(); //set the time constants for rt, at, and tav static t_CKFLOAT computeTimeConst(t_CKDUR t) { //AT = 1 - e ^ (-2.2T/tsrate() * 1.0 / 1000.0; //setters for the timing constants void Dyno_Data::setAttackTime(t_CKDUR t) { at = computeTimeConst(t); } void Dyno_Data::setReleaseTime(t_CKDUR t) { rt = computeTimeConst(t); } void Dyno_Data::setRatio(t_CKFLOAT newRatio) { this->slopeAbove = 1.0 / newRatio; this->slopeBelow = 1.0; } t_CKFLOAT Dyno_Data::getRatio() { return this->slopeBelow / this->slopeAbove; } //TODO: come up with better/good presets? //presets for the dynomics processor void Dyno_Data::limit() { slopeAbove = 0.1; // 10:1 compression above thresh slopeBelow = 1.0; // no compression below thresh = 0.5; at = computeTimeConst( 5.0 * ms ); rt = computeTimeConst( 300.0 * ms ); externalSideInput = 0; } void Dyno_Data::compress() { slopeAbove = 0.5; // 2:1 compression slopeBelow = 1.0; thresh = 0.5; at = computeTimeConst( 5.0 * ms ); rt = computeTimeConst( 500.0 * ms ); externalSideInput = 0; } void Dyno_Data::gate() { slopeAbove = 1.0; slopeBelow = 100000000; // infinity (more or less) thresh = 0.1; at = computeTimeConst( 11.0 * ms ); rt = computeTimeConst( 100.0 * ms ); externalSideInput = 0; } void Dyno_Data::expand() { slopeAbove = 2.0; // 1:2 expansion slopeBelow = 1.0; thresh = 0.5; at = computeTimeConst( 20.0 * ms ); rt = computeTimeConst( 400.0 * ms ); externalSideInput = 0; } void Dyno_Data::duck() { slopeAbove = 0.5; // when sideInput rises above thresh, gain starts going slopeBelow = 1.0; // down. it'll drop more as sideInput gets louder. thresh = 0.1; at = computeTimeConst( 10.0 * ms ); rt = computeTimeConst( 1000.0 * ms ); externalSideInput = 1; } //controls for the preset modes CK_DLL_CTRL( dyno_ctrl_limit ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->limit(); } CK_DLL_CTRL( dyno_ctrl_compress ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->compress(); } CK_DLL_CTRL( dyno_ctrl_gate ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->gate(); } CK_DLL_CTRL( dyno_ctrl_expand ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->expand(); } CK_DLL_CTRL( dyno_ctrl_duck ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->duck(); } //additional controls: thresh CK_DLL_CTRL( dyno_ctrl_thresh ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->thresh = GET_CK_FLOAT(ARGS); RETURN->v_float = (t_CKFLOAT)d->thresh; } CK_DLL_CGET( dyno_cget_thresh ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_float = (t_CKFLOAT)d->thresh; } //additional controls: attackTime CK_DLL_CTRL( dyno_ctrl_attackTime ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->setAttackTime( GET_CK_FLOAT(ARGS) ); RETURN->v_dur = d->timeConstToDur(d->at); } CK_DLL_CGET( dyno_cget_attackTime ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_dur = d->timeConstToDur(d->at); } //additional controls: releaseTime CK_DLL_CTRL( dyno_ctrl_releaseTime ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->setReleaseTime( GET_CK_FLOAT(ARGS) ); RETURN->v_dur = d->timeConstToDur(d->rt); } CK_DLL_CGET( dyno_cget_releaseTime ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_dur = d->timeConstToDur(d->rt); } //additional controls: ratio CK_DLL_CTRL( dyno_ctrl_ratio ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->setRatio( GET_CK_FLOAT(ARGS) ); RETURN->v_float = d->getRatio(); } CK_DLL_CGET( dyno_cget_ratio ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_float = d->getRatio(); } //additional controls: slopeBelow CK_DLL_CTRL( dyno_ctrl_slopeBelow ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->slopeBelow = GET_CK_FLOAT(ARGS); RETURN->v_float = d->slopeBelow; } CK_DLL_CGET( dyno_cget_slopeBelow ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_float = d->slopeBelow; } //additional controls: slopeAbove CK_DLL_CTRL( dyno_ctrl_slopeAbove ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->slopeAbove = GET_CK_FLOAT(ARGS); RETURN->v_float = d->slopeAbove; } CK_DLL_CGET( dyno_cget_slopeAbove ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_float = d->slopeAbove; } //additional controls: sideInput CK_DLL_CTRL( dyno_ctrl_sideInput ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->sideInput = GET_CK_FLOAT(ARGS); RETURN->v_float = d->sideInput; } CK_DLL_CGET( dyno_cget_sideInput ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_float = d->sideInput; } //additional controls: externalSideInput CK_DLL_CTRL( dyno_ctrl_externalSideInput ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); d->externalSideInput = GET_CK_INT(ARGS); RETURN->v_int = d->externalSideInput; } CK_DLL_CGET( dyno_cget_externalSideInput ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); RETURN->v_int = d->externalSideInput; } //constructor CK_DLL_CTOR( dyno_ctor ) { OBJ_MEMBER_UINT(SELF, dyno_offset_data) = (t_CKUINT)new Dyno_Data; } CK_DLL_DTOR( dyno_dtor ) { delete (Dyno_Data *)OBJ_MEMBER_UINT(SELF, dyno_offset_data); OBJ_MEMBER_UINT(SELF, dyno_offset_data) = 0; } // recomputes envelope, determines how the current amp envelope compares with // thresh, applies the appropriate new slope depending on how far above/below // the threshold the current envelope is. CK_DLL_TICK( dyno_tick ) { Dyno_Data * d = ( Dyno_Data * )OBJ_MEMBER_UINT(SELF, dyno_offset_data); // only change sideInput if we're not using an external ctrl signal. // otherwise we'll just use whatever the user sent us last as the ctrl signal if(!d->externalSideInput) d->sideInput = in >= 0 ? in : -in; // 'a' is signal left after subtracting xd (to recompute sideChain envelope) double a = d->sideInput - d->xd; // a is only needed if positive to pull the envelope up, not to bring it down if ( a < 0 ) a=0; // the attack/release (peak) exponential filter to guess envelope d->xd = d->xd * (1 - d->rt) + d->at * a; // if you were to use the rms filter, // it would probably look, a sumpthin' like this // d->xd = TAV * in*in + (1+TAV) * d->xd // decide which slope to use, depending on whether we're below/above thresh double slope = d->xd > d->thresh ? d->slopeAbove : d->slopeBelow; // the gain function - apply the slope chosen above double f = slope == 1.0 ? 1.0 : pow( d->xd / d->thresh, slope - 1.0 ); // apply the gain found above to input sample *out = f * in; return TRUE; } #define LiSa_MAXVOICES 100 #define LiSa_MAXBUFSIZE 4410000 //----------------------------------------------------------------------------- // name: LiSaMulti_data // desc: ... //----------------------------------------------------------------------------- struct LiSaMulti_data { SAMPLE * mdata; t_CKINT mdata_len; t_CKINT maxvoices; t_CKINT loop_start[LiSa_MAXVOICES], loop_end[LiSa_MAXVOICES], loop_end_rec; t_CKINT rindex; // record and play indices t_CKBOOL record, looprec, loopplay[LiSa_MAXVOICES], reset, append, play[LiSa_MAXVOICES], bi[LiSa_MAXVOICES]; t_CKFLOAT coeff; // feedback coeff t_CKDOUBLE p_inc[LiSa_MAXVOICES], pindex[LiSa_MAXVOICES]; // playback increment // ramp stuff t_CKDOUBLE rampup_len[LiSa_MAXVOICES], rampdown_len[LiSa_MAXVOICES], rec_ramplen, rec_ramplen_inv; t_CKDOUBLE rampup_len_inv[LiSa_MAXVOICES], rampdown_len_inv[LiSa_MAXVOICES]; t_CKDOUBLE rampctr[LiSa_MAXVOICES]; t_CKBOOL rampup[LiSa_MAXVOICES], rampdown[LiSa_MAXVOICES]; t_CKINT track; // allocate memory, length in samples inline int buffer_alloc(t_CKINT length) { mdata = (SAMPLE *)malloc(length * sizeof(SAMPLE)); if(!mdata) { fprintf(stderr, "LiSaBasic: unable to allocate memory!\n"); return false; } mdata_len = length; maxvoices = 10; // default; user can set rec_ramplen = 0.; rec_ramplen_inv = 1.; track = 0; for (t_CKINT i=0; i < LiSa_MAXVOICES; i++) { loop_start[i] = 0; loop_end[i] = loop_end_rec = length; pindex[i] = rindex = 0; play[i] = record = bi[i] = false; looprec = loopplay[i] = true; coeff = 0.; p_inc[i] = 1.; // ramp stuff rampup[i] = rampdown[i] = false; rampup_len[i] = rampdown_len[i] = 0.; rampup_len_inv[i] = rampdown_len_inv[i] = 1.; rampctr[i] = 0.; } return true; } // dump a sample into the buffer; retain existing sample, scaled by "coeff" inline void recordSamp(SAMPLE insample) { SAMPLE tempsample; if(record) { if(looprec) { if(rindex >= loop_end_rec) rindex = 0; tempsample = coeff * mdata[rindex] + insample; //mdata[rindex] = coeff * mdata[rindex] + insample; //rindex++; } else { if (rindex < loop_end_rec) { //mdata[rindex] = coeff * mdata[rindex] + insample; tempsample = coeff * mdata[rindex] + insample; //rindex++; } else { record = 0; return; } } // ramp stuff here if(rindex < rec_ramplen) { tempsample *= (rindex * rec_ramplen_inv); } else if(rindex > (loop_end_rec - rec_ramplen)) { tempsample *= (loop_end_rec - rindex) * rec_ramplen_inv; } mdata[rindex] = tempsample; rindex++; } } // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later) // increment play index inline SAMPLE getNextSamp(t_CKINT which) { // constrain if(loopplay[which]) { if(bi[which]) { // change direction if bidirectional mode if(pindex[which] >= loop_end[which] || pindex[which] < loop_start[which]) { pindex[which] -= p_inc[which]; p_inc[which] = -p_inc[which]; } } while(pindex[which] >= loop_end[which]) pindex[which] = loop_start[which] + (pindex[which] - loop_end[which]); while(pindex[which] < loop_start[which]) pindex[which] = loop_end[which] - (loop_start[which] - pindex[which]); } else if(pindex[which] >= loop_end[which] || pindex[which] < loop_start[which]) { play[which] = 0; //fprintf(stderr, "turning voice %d off!\n", which); return (SAMPLE) 0.; } // interp t_CKINT whereTrunc = (t_CKINT) pindex[which]; t_CKDOUBLE whereFrac = pindex[which] - (t_CKDOUBLE)whereTrunc; t_CKINT whereNext = whereTrunc + 1; if((whereNext) == loop_end[which]) whereNext = loop_start[which]; pindex[which] += p_inc[which]; t_CKDOUBLE outsample; outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac; // ramp stuff if(rampup[which]) { outsample *= rampctr[which]++ * rampup_len_inv[which]; //remove divide if(rampctr[which] >= rampup_len[which]) rampup[which] = false; } else if(rampdown[which]) { outsample *= (rampdown_len[which] - rampctr[which]++) * rampdown_len_inv[which]; if(rampctr[which] >= rampdown_len[which]) { rampdown[which] = false; play[which] = false; } } return (SAMPLE)outsample; } // grab a sample from the buffer, with linear interpolation (add prc's SINC interp later) // given a position within the buffer inline SAMPLE getSamp(t_CKDOUBLE where, t_CKINT which) { // constrain if(where >= loop_end[which]) where = loop_end[which] - 1.; if(where < loop_start[which]) where = loop_start[which]; // interp t_CKINT whereTrunc = (t_CKINT) where; t_CKDOUBLE whereFrac = where - (t_CKDOUBLE)whereTrunc; t_CKINT whereNext = whereTrunc + 1; if((whereNext) == loop_end[which]) whereNext = loop_start[which]; t_CKDOUBLE outsample; outsample = (t_CKDOUBLE)mdata[whereTrunc] + (t_CKDOUBLE)(mdata[whereNext] - mdata[whereTrunc]) * whereFrac; return (SAMPLE)outsample; } // ramp stuff inline void ramp_up(t_CKINT voicenum, t_CKDUR uptime) { // fprintf(stderr, "ramping up voice %d", voicenum); rampup[voicenum] = true; play[voicenum] = true; rampup_len[voicenum] = (t_CKDOUBLE)uptime; if(rampup_len[voicenum] > 0.) rampup_len_inv[voicenum] = 1./rampup_len[voicenum]; else rampup_len[voicenum] = 1.; // check to make sure we are not mid ramping down if(rampdown[voicenum]) { rampctr[voicenum] = rampup_len[voicenum] * (1. - rampctr[voicenum]/rampdown_len[voicenum]); rampdown[voicenum] = false; } else rampctr[voicenum] = 0; } inline void ramp_down(t_CKINT voicenum, t_CKDUR downtime) { rampdown[voicenum] = true; rampdown_len[voicenum] = (t_CKDOUBLE)downtime; if(rampdown_len[voicenum] > 0.) rampdown_len_inv[voicenum] = 1./rampdown_len[voicenum]; else rampdown_len[voicenum] = 1.; // check to make sure we are not mid ramping up if(rampup[voicenum]) { rampctr[voicenum] = rampdown_len[voicenum] * (1. - rampctr[voicenum]/rampup_len[voicenum]); rampup[voicenum] = false; } else rampctr[voicenum] = 0; } inline void set_rec_ramplen(t_CKDUR newlen) { rec_ramplen = (t_CKDOUBLE)newlen; if(rec_ramplen > 0.) rec_ramplen_inv = 1./rec_ramplen; else rec_ramplen_inv = 1.; } // tick_multi: mono // may want to make multichannel version, // but could also just run multiple LiSas to get multi channel // this is probably not ideal for, say, a 16 channel setup, but maybe who cares inline SAMPLE tick_multi( SAMPLE in) { if(!mdata) return (SAMPLE) 0.; recordSamp(in); SAMPLE tempsample = 0.; if(track==0) { for (t_CKINT i=0; itick_multi( in ); return TRUE; } //----------------------------------------------------------------------------- // name: LiSaMulti_size() // desc: set size of buffer allocation //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_size ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKDUR buflen = GET_NEXT_DUR(ARGS); if (buflen > LiSa_MAXBUFSIZE) { fprintf(stderr, "buffer size request too large, resizing\n"); buflen = LiSa_MAXBUFSIZE; } d->buffer_alloc((t_CKINT)buflen); RETURN->v_dur = (t_CKDUR)buflen; } //----------------------------------------------------------------------------- // name: LiSaMulti_start_record() // desc: CTRL function ... //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_start_record ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->record = GET_NEXT_INT(ARGS); RETURN->v_int = (t_CKINT)d->record; } //----------------------------------------------------------------------------- // name: LiSaMulti_start_play() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_start_play ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->play[which] = GET_NEXT_INT(ARGS); //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]); RETURN->v_int = (t_CKINT)d->play[which]; } //----------------------------------------------------------------------------- // name: LiSaMulti_start_play() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_start_play0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->play[0] = GET_NEXT_INT(ARGS); //fprintf(stderr, "voice %d playing = %d\n", which, d->play[which]); RETURN->v_int = (t_CKINT)d->play[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_rate() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_rate ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->p_inc[which] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS); //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]); RETURN->v_int = (t_CKINT)d->p_inc[which]; } CK_DLL_CTRL( LiSaMulti_ctrl_rate0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->p_inc[0] = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS); //fprintf(stderr, "setting voice %d rate to %f\n", which, d->p_inc[which]); RETURN->v_int = (t_CKINT)d->p_inc[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_pindex() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_pindex ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->pindex[which] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->pindex[which]; } CK_DLL_CTRL( LiSaMulti_ctrl_pindex0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->pindex[0] = (t_CKDOUBLE)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->pindex[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_pindex() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_pindex ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); // return RETURN->v_dur = (t_CKDUR)d->pindex[which]; } CK_DLL_CGET( LiSaMulti_cget_pindex0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_dur = (t_CKDUR)d->pindex[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_pindex() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_rindex ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->rindex = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->rindex; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_pindex() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_rindex ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_dur = (t_CKDUR)d->rindex; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_lstart() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_lstart ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->loop_start[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->loop_start[which]; } CK_DLL_CTRL( LiSaMulti_ctrl_lstart0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->loop_start[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->loop_start[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_lstart() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_lstart ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); // return RETURN->v_dur = (t_CKDUR)d->loop_start[which]; } CK_DLL_CGET( LiSaMulti_cget_lstart0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_dur = (t_CKDUR)d->loop_start[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_lend() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_lend ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->loop_end[which] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); } CK_DLL_CTRL( LiSaMulti_ctrl_lend0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->loop_end[0] = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->loop_end[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_lend() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_lend ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); // return RETURN->v_dur = (t_CKDUR)d->loop_end[which]; } CK_DLL_CGET( LiSaMulti_cget_lend0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_dur = (t_CKDUR)d->loop_end[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_loop() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_loop ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->loopplay[which] = (t_CKBOOL)GET_NEXT_INT(ARGS); } CK_DLL_CTRL( LiSaMulti_ctrl_loop0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->loopplay[0] = (t_CKBOOL)GET_NEXT_INT(ARGS); RETURN->v_int = (t_CKINT)d->loopplay[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_loop() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_loop ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); // return RETURN->v_int = (t_CKINT)d->loopplay[which]; } CK_DLL_CGET( LiSaMulti_cget_loop0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = (t_CKINT)d->loopplay[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_bi() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_bi ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); d->bi[which] = (t_CKBOOL)GET_NEXT_INT(ARGS); RETURN->v_int = (t_CKINT)d->bi[which]; } CK_DLL_CTRL( LiSaMulti_ctrl_bi0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->bi[0] = (t_CKBOOL)GET_NEXT_INT(ARGS); RETURN->v_int = (t_CKINT)d->bi[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_bi() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_bi ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT which = GET_NEXT_INT(ARGS); // return RETURN->v_int = (t_CKINT)d->bi[which]; } CK_DLL_CGET( LiSaMulti_cget_bi0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = (t_CKINT)d->bi[0]; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_loop_end_rec() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_loop_end_rec ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->loop_end_rec = /* gewang-> */(t_CKINT)GET_NEXT_DUR(ARGS); RETURN->v_dur = (t_CKDUR)d->loop_end_rec; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_loop_end_rec() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_loop_end_rec ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_dur = (t_CKDUR)d->loop_end_rec; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_loop_rec() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_loop_rec ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->looprec = (t_CKBOOL)GET_NEXT_INT(ARGS); RETURN->v_int = (t_CKINT)d->looprec; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_loop_rec() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_loop_rec ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = (t_CKINT)d->looprec; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_coeff() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_coeff ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->coeff = (t_CKDOUBLE)GET_NEXT_FLOAT(ARGS); RETURN->v_float = (t_CKFLOAT)d->coeff; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_coeff() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_coeff ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_float = (t_CKFLOAT)d->coeff; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_clear() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_clear ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->clear_buf(); } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_voice() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_voice ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = (t_CKINT)d->get_free_voice(); } // ramp stuff //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_rampup() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_rampup ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT voice = GET_NEXT_INT(ARGS); t_CKDUR len = GET_NEXT_DUR(ARGS); d->ramp_up(voice, len); RETURN->v_dur = (t_CKDUR)len; } CK_DLL_CTRL( LiSaMulti_ctrl_rampup0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKDUR len = GET_NEXT_DUR(ARGS); d->ramp_up(0, len); RETURN->v_dur = (t_CKDUR)len; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_rampdown() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_rampdown ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT voice = GET_NEXT_INT(ARGS); t_CKDUR len = GET_NEXT_DUR(ARGS); d->ramp_down(voice, len); RETURN->v_dur = (t_CKDUR)len; } CK_DLL_CTRL( LiSaMulti_ctrl_rampdown0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKDUR len = GET_NEXT_DUR(ARGS); d->ramp_down(0, len); RETURN->v_dur = (t_CKDUR)len; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_rec_ramplen() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_rec_ramplen ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKDUR newramplen = GET_NEXT_DUR(ARGS); d->set_rec_ramplen(newramplen); RETURN->v_dur = (t_CKDUR)newramplen; } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_maxvoices() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_maxvoices ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->maxvoices = GET_NEXT_INT(ARGS); RETURN->v_int = d->maxvoices; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_maxvoices() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_maxvoices ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = d->maxvoices; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_samp() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_value ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKINT voice = GET_NEXT_INT(ARGS); t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS); // return RETURN->v_dur = (t_CKDUR)d->getSamp(where, voice); } CK_DLL_CGET( LiSaMulti_cget_value0 ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); t_CKDOUBLE where = (t_CKDOUBLE) GET_NEXT_DUR(ARGS); // return RETURN->v_dur = (t_CKDUR)d->getSamp(where, 0); } //----------------------------------------------------------------------------- // name: LiSaMulti_ctrl_track() // desc: CTRL function //----------------------------------------------------------------------------- CK_DLL_CTRL( LiSaMulti_ctrl_track ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); d->track = (t_CKINT)GET_NEXT_INT(ARGS); RETURN->v_int = d->track; } //----------------------------------------------------------------------------- // name: LiSaMulti_cget_sync() // desc: CGET function //----------------------------------------------------------------------------- CK_DLL_CGET( LiSaMulti_cget_track ) { LiSaMulti_data * d = (LiSaMulti_data *)OBJ_MEMBER_UINT(SELF, LiSaMulti_offset_data); // return RETURN->v_int = d->track; } //----------------------------------------------------------------------------- // name: LiSaMulti_pmsg() // desc: PMSG function ... //----------------------------------------------------------------------------- CK_DLL_PMSG(LiSaMulti_pmsg ) { return FALSE; } chuck-1.2.0.8.dfsg/src/ugen_xxx.h0000644000175000017500000001615010600421721015146 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ugen_xxx.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __UGEN_XXX_H__ #define __UGEN_XXX_H__ #include "chuck_dl.h" // query DLL_QUERY xxx_query( Chuck_DL_Query * query ); // global struct Chuck_Type; extern Chuck_Type * g_t_dac; extern Chuck_Type * g_t_adc; // stereo CK_DLL_CTOR( stereo_ctor ); CK_DLL_CTRL( stereo_ctrl_pan ); CK_DLL_CGET( stereo_cget_pan ); // multi CK_DLL_CTOR( multi_ctor ); CK_DLL_CTRL( multi_ctrl_pan ); CK_DLL_CGET( multi_cget_pan ); CK_DLL_CGET( multi_cget_chan ); // bunghole CK_DLL_TICK( bunghole_tick ); // pan2 CK_DLL_CTOR( pan2_ctor ); CK_DLL_DTOR( pan2_dtor ); CK_DLL_CTRL( pan2_ctrl_value ); CK_DLL_CGET( pan2_cget_value ); // MIX2 CK_DLL_CTOR( mix2_ctor ); CK_DLL_CTOR( mix2_dtor ); CK_DLL_CTRL( mix2_ctrl_value ); CK_DLL_CGET( mix2_cget_value ); // noise CK_DLL_TICK( noise_tick ); // cnoise CK_DLL_CTOR( cnoise_ctor ); CK_DLL_DTOR( cnoise_dtor ); CK_DLL_TICK( cnoise_tick ); CK_DLL_CTRL( cnoise_ctrl_mode ); CK_DLL_CTRL( cnoise_ctrl_fprob ); // impulse CK_DLL_CTOR( impulse_ctor ); CK_DLL_DTOR( impulse_dtor ); CK_DLL_TICK( impulse_tick ); CK_DLL_CTRL( impulse_ctrl_next ); CK_DLL_CGET( impulse_cget_next ); // step CK_DLL_CTOR( step_ctor ); CK_DLL_DTOR( step_dtor ); CK_DLL_TICK( step_tick ); CK_DLL_CTRL( step_ctrl_next ); CK_DLL_CGET( step_cget_next ); // gain CK_DLL_CTOR( gain_ctor ); CK_DLL_DTOR( gain_dtor ); CK_DLL_TICK( gain_tick ); CK_DLL_CTRL( gain_ctrl_value ); CK_DLL_CGET( gain_cget_value ); // dyno (Matt Hoffman + Graham Coleman) // TODO: add soft knee option CK_DLL_CTOR( dyno_ctor ); CK_DLL_DTOR( dyno_dtor ); CK_DLL_TICK( dyno_tick ); CK_DLL_CTRL( dyno_ctrl_limit ); CK_DLL_CTRL( dyno_ctrl_compress ); CK_DLL_CTRL( dyno_ctrl_expand ); CK_DLL_CTRL( dyno_ctrl_gate ); CK_DLL_CTRL( dyno_ctrl_duck ); CK_DLL_CTRL( dyno_ctrl_thresh ); CK_DLL_CGET( dyno_cget_thresh ); CK_DLL_CTRL( dyno_ctrl_attackTime ); CK_DLL_CGET( dyno_cget_attackTime ); CK_DLL_CTRL( dyno_ctrl_releaseTime ); CK_DLL_CGET( dyno_cget_releaseTime ); CK_DLL_CTRL( dyno_ctrl_ratio ); CK_DLL_CGET( dyno_cget_ratio ); CK_DLL_CTRL( dyno_ctrl_slopeBelow ); CK_DLL_CGET( dyno_cget_slopeBelow ); CK_DLL_CTRL( dyno_ctrl_slopeAbove ); CK_DLL_CGET( dyno_cget_slopeAbove ); CK_DLL_CTRL( dyno_ctrl_externalSideInput ); CK_DLL_CGET( dyno_cget_externalSideInput ); CK_DLL_CTRL( dyno_ctrl_sideInput ); CK_DLL_CGET( dyno_cget_sideInput ); // halfrect CK_DLL_TICK( halfrect_tick ); // fullrect CK_DLL_TICK( fullrect_tick ); // zerox CK_DLL_CTOR( zerox_ctor ); CK_DLL_DTOR( zerox_dtor ); CK_DLL_TICK( zerox_tick ); // delayp CK_DLL_CTOR( delayp_ctor ); CK_DLL_DTOR( delayp_dtor ); CK_DLL_PMSG( delayp_pmsg ); CK_DLL_TICK( delayp_tick ); CK_DLL_CTRL( delayp_ctrl_delay ); CK_DLL_CGET( delayp_cget_delay ); CK_DLL_CTRL( delayp_ctrl_window ); CK_DLL_CGET( delayp_cget_window ); CK_DLL_CTRL( delayp_ctrl_max ); CK_DLL_CGET( delayp_cget_max ); // sndbuf CK_DLL_CTOR( sndbuf_ctor ); CK_DLL_DTOR( sndbuf_dtor ); CK_DLL_TICK( sndbuf_tick ); CK_DLL_CTRL( sndbuf_ctrl_read ); CK_DLL_CGET( sndbuf_cget_read ); CK_DLL_CTRL( sndbuf_ctrl_write ); CK_DLL_CGET( sndbuf_cget_write ); CK_DLL_CTRL( sndbuf_ctrl_pos ); CK_DLL_CGET( sndbuf_cget_pos ); CK_DLL_CTRL( sndbuf_ctrl_loop ); CK_DLL_CGET( sndbuf_cget_loop ); CK_DLL_CTRL( sndbuf_ctrl_interp ); CK_DLL_CGET( sndbuf_cget_interp ); CK_DLL_CTRL( sndbuf_ctrl_rate ); CK_DLL_CGET( sndbuf_cget_rate ); CK_DLL_CTRL( sndbuf_ctrl_play ); CK_DLL_CGET( sndbuf_cget_play ); CK_DLL_CTRL( sndbuf_ctrl_freq ); CK_DLL_CGET( sndbuf_cget_freq ); CK_DLL_CTRL( sndbuf_ctrl_phase ); CK_DLL_CGET( sndbuf_cget_phase ); CK_DLL_CTRL( sndbuf_ctrl_channel ); CK_DLL_CGET( sndbuf_cget_channel ); CK_DLL_CTRL( sndbuf_ctrl_chunks ); CK_DLL_CGET( sndbuf_cget_chunks ); CK_DLL_CTRL( sndbuf_ctrl_phase_offset ); CK_DLL_CGET( sndbuf_cget_samples ); CK_DLL_CGET( sndbuf_cget_length ); CK_DLL_CGET( sndbuf_cget_channels ); CK_DLL_CGET( sndbuf_cget_valueAt ); // LiSa (Dan Trueman) CK_DLL_CTOR( LiSaMulti_ctor ); CK_DLL_DTOR( LiSaMulti_dtor ); CK_DLL_TICK( LiSaMulti_tick ); CK_DLL_PMSG( LiSaMulti_pmsg ); CK_DLL_CTRL( LiSaMulti_size ); CK_DLL_CTRL( LiSaMulti_start_record ); CK_DLL_CTRL( LiSaMulti_start_play ); CK_DLL_CTRL( LiSaMulti_start_play0 ); CK_DLL_CTRL( LiSaMulti_ctrl_rate ); CK_DLL_CTRL( LiSaMulti_ctrl_rate0 ); CK_DLL_CTRL( LiSaMulti_ctrl_pindex ); CK_DLL_CGET( LiSaMulti_cget_pindex ); CK_DLL_CTRL( LiSaMulti_ctrl_pindex0 ); CK_DLL_CGET( LiSaMulti_cget_pindex0 ); CK_DLL_CTRL( LiSaMulti_ctrl_rindex ); CK_DLL_CGET( LiSaMulti_cget_rindex ); CK_DLL_CTRL( LiSaMulti_ctrl_lstart ); CK_DLL_CGET( LiSaMulti_cget_lstart ); CK_DLL_CTRL( LiSaMulti_ctrl_lend ); CK_DLL_CGET( LiSaMulti_cget_lend ); CK_DLL_CTRL( LiSaMulti_ctrl_lstart0 ); CK_DLL_CGET( LiSaMulti_cget_lstart0 ); CK_DLL_CTRL( LiSaMulti_ctrl_lend0 ); CK_DLL_CGET( LiSaMulti_cget_lend0 ); CK_DLL_CTRL( LiSaMulti_ctrl_loop ); CK_DLL_CGET( LiSaMulti_cget_loop ); CK_DLL_CTRL( LiSaMulti_ctrl_bi ); CK_DLL_CGET( LiSaMulti_cget_bi ); CK_DLL_CTRL( LiSaMulti_ctrl_loop0 ); CK_DLL_CGET( LiSaMulti_cget_loop0 ); CK_DLL_CTRL( LiSaMulti_ctrl_bi0 ); CK_DLL_CGET( LiSaMulti_cget_bi0 ); CK_DLL_CTRL( LiSaMulti_ctrl_loop_end_rec ); CK_DLL_CGET( LiSaMulti_cget_loop_end_rec ); CK_DLL_CTRL( LiSaMulti_ctrl_looprec ); CK_DLL_CGET( LiSaMulti_cget_looprec ); CK_DLL_CTRL( LiSaMulti_ctrl_coeff ); CK_DLL_CGET( LiSaMulti_cget_coeff ); CK_DLL_CTRL( LiSaMulti_ctrl_clear ); CK_DLL_CGET( LiSaMulti_cget_voice ); CK_DLL_CTRL( LiSaMulti_ctrl_maxvoices ); CK_DLL_CGET( LiSaMulti_cget_maxvoices ); CK_DLL_CGET( LiSaMulti_cget_value ); CK_DLL_CGET( LiSaMulti_cget_value0 ); CK_DLL_CTRL( LiSaMulti_ctrl_track ); CK_DLL_CGET( LiSaMulti_cget_track ); // ramp stuff CK_DLL_CTRL( LiSaMulti_ctrl_rampup ); CK_DLL_CTRL( LiSaMulti_ctrl_rampdown ); CK_DLL_CTRL( LiSaMulti_ctrl_rampup0 ); CK_DLL_CTRL( LiSaMulti_ctrl_rampdown0 ); CK_DLL_CTRL( LiSaMulti_ctrl_rec_ramplen ); #endif chuck-1.2.0.8.dfsg/src/ulib_machine.cpp0000644000175000017500000001234710600421721016257 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_machine.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "ulib_machine.h" #include "chuck_type.h" #include "chuck_vm.h" #include "chuck_errmsg.h" #include "chuck_globals.h" //----------------------------------------------------------------------------- // name: machine_query() // desc: query entry point //----------------------------------------------------------------------------- DLL_QUERY machine_query( Chuck_DL_Query * QUERY ) { // get global env instance Chuck_Env * env = Chuck_Env::instance(); // set name of this query QUERY->setname( QUERY, "Machine" ); /*! \nameinfo ChucK runtime interface to the virtual machine. this interface can be used to manage shreds. They are similar to the On-the-fly Programming Commands, except these are invoked from within a ChucK program, and are accessible to the timing mechanism. */ // register deprecate type_engine_register_deprecate( env, "machine", "Machine" ); // class QUERY->begin_class( QUERY, "Machine", "Object" ); // add add //! compile and spork a new shred from file at 'path' into the VM now //! returns the shred ID //! (see example/machine.ck) QUERY->add_sfun( QUERY, machine_add_impl, "int", "add" ); QUERY->add_arg( QUERY, "string", "path" ); // add spork //! same as add // QUERY->add_sfun( QUERY, machine_add_impl, "int", "spork" ); // QUERY->add_arg( QUERY, "string", "path" ); // add remove //! remove shred from VM by shred ID (returned by add/spork) QUERY->add_sfun( QUERY, machine_remove_impl, "int", "remove" ); QUERY->add_arg( QUERY, "int", "id" ); // add replace //! replace shred with new shred from file //! returns shred ID , or 0 on error QUERY->add_sfun( QUERY, machine_replace_impl, "int", "replace" ); QUERY->add_arg( QUERY, "int", "id" ); QUERY->add_arg( QUERY, "string", "path" ); // add replace //! replace shred with new shred from file //! returns shred ID , or 0 on error QUERY->add_sfun( QUERY, machine_crash_impl, "void", "crash" ); // add status //! display current status of VM //! (see example/status.ck) QUERY->add_sfun( QUERY, machine_status_impl, "int", "status" ); // end class QUERY->end_class( QUERY ); return TRUE; } static Chuck_VM * the_vm = NULL; static Chuck_Compiler * the_compiler = NULL; static proc_msg_func the_func = NULL; //----------------------------------------------------------------------------- // name: machine_init() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL machine_init( Chuck_Compiler * compiler, proc_msg_func proc_msg ) { the_vm = g_vm; the_compiler = compiler; the_func = proc_msg; return TRUE; } // add CK_DLL_SFUN( machine_crash_impl ) { fprintf( stderr, "[chuck]: crashing...\n" ); *(int *)0 = 0; } // add CK_DLL_SFUN( machine_add_impl ) { const char * v = GET_CK_STRING(ARGS)->str.c_str(); Net_Msg msg; msg.type = MSG_ADD; strcpy( msg.buffer, v ); RETURN->v_int = (int)the_func( the_vm, the_compiler, &msg, TRUE, NULL ); } // remove CK_DLL_SFUN( machine_remove_impl ) { t_CKINT v = GET_CK_INT(ARGS); Net_Msg msg; msg.type = MSG_REMOVE; msg.param = v; RETURN->v_int = (int)the_func( the_vm, the_compiler, &msg, TRUE, NULL ); } // replace CK_DLL_SFUN( machine_replace_impl ) { t_CKINT v = GET_NEXT_INT(ARGS); const char * v2 = GET_NEXT_STRING(ARGS)->str.c_str(); Net_Msg msg; msg.type = MSG_REPLACE; msg.param = v; strcpy( msg.buffer, v2 ); RETURN->v_int = (int)the_func( the_vm, the_compiler, &msg, TRUE, NULL ); } // status CK_DLL_SFUN( machine_status_impl ) { Net_Msg msg; msg.type = MSG_STATUS; RETURN->v_int = (int)the_func( the_vm, the_compiler, &msg, TRUE, NULL ); } chuck-1.2.0.8.dfsg/src/ulib_machine.h0000644000175000017500000000407510600421721015723 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_machine.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __ULIB_MACHINE_H__ #define __ULIB_MACHINE_H__ #include "chuck_dl.h" #include "chuck_otf.h" // forward reference struct Chuck_VM; struct Chuck_Compiler; // query DLL_QUERY machine_query( Chuck_DL_Query * QUERY ); typedef t_CKUINT (* proc_msg_func)( Chuck_VM *, Chuck_Compiler *, Net_Msg *, t_CKBOOL, void * ); t_CKBOOL machine_init( Chuck_Compiler * compiler, proc_msg_func func ); // exports CK_DLL_SFUN( machine_crash_impl ); CK_DLL_SFUN( machine_add_impl ); CK_DLL_SFUN( machine_spork_impl ); CK_DLL_SFUN( machine_remove_impl ); CK_DLL_SFUN( machine_replace_impl ); CK_DLL_SFUN( machine_status_impl ); #endif chuck-1.2.0.8.dfsg/src/ulib_math.cpp0000644000175000017500000002563310600421721015606 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_math.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "chuck_type.h" #include "ulib_math.h" #include "util_math.h" #include "ulib_std.h" #ifdef __PLATFORM_WIN32__ #include #endif static double g_pi = ONE_PI; static double g_twopi = TWO_PI; static double g_e = ::exp( 1.0 ); // query DLL_QUERY libmath_query( Chuck_DL_Query * QUERY ) { // get global Chuck_Env * env = Chuck_Env::instance(); // name QUERY->setname( QUERY, "Math" ); /*! \example math.sin( math.pi /2.0 ) => stdout; */ // register deprecate type_engine_register_deprecate( env, "math", "Math" ); // add class QUERY->begin_class( QUERY, "Math", "Object" ); // add abs QUERY->add_sfun( QUERY, abs_impl, "int", "abs" ); QUERY->add_arg( QUERY, "int", "value" ); // add fabs QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" ); QUERY->add_arg( QUERY, "float", "value" ); // add sgn QUERY->add_sfun( QUERY, sgn_impl, "float", "sgn" ); QUERY->add_arg( QUERY, "float", "value" ); // sin QUERY->add_sfun( QUERY, sin_impl, "float", "sin" ); QUERY->add_arg( QUERY, "float", "x" ); // cos QUERY->add_sfun( QUERY, cos_impl, "float", "cos" ); QUERY->add_arg( QUERY, "float", "x" ); // tan QUERY->add_sfun( QUERY, tan_impl, "float", "tan" ); QUERY->add_arg( QUERY, "float", "x" ); // asin QUERY->add_sfun( QUERY, asin_impl, "float", "asin" ); QUERY->add_arg( QUERY, "float", "x" ); // acos QUERY->add_sfun( QUERY, acos_impl, "float", "acos" ); QUERY->add_arg( QUERY, "float", "x" ); // atan QUERY->add_sfun( QUERY, atan_impl, "float", "atan" ); QUERY->add_arg( QUERY, "float", "x" ); // atan2 QUERY->add_sfun( QUERY, atan2_impl, "float", "atan2" ); QUERY->add_arg( QUERY, "float", "y" ); QUERY->add_arg( QUERY, "float", "x" ); // sinh QUERY->add_sfun( QUERY, sinh_impl, "float", "sinh" ); QUERY->add_arg( QUERY, "float", "x" ); // cosh QUERY->add_sfun( QUERY, cosh_impl, "float", "cosh" ); QUERY->add_arg( QUERY, "float", "x" ); // tanh QUERY->add_sfun( QUERY, tanh_impl, "float", "tanh" ); QUERY->add_arg( QUERY, "float", "x" ); // hypot QUERY->add_sfun( QUERY, hypot_impl, "float", "hypot" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // pow QUERY->add_sfun( QUERY, pow_impl, "float", "pow" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // sqrt QUERY->add_sfun( QUERY, sqrt_impl, "float", "sqrt" ); QUERY->add_arg( QUERY, "float", "x" ); // exp QUERY->add_sfun( QUERY, exp_impl, "float", "exp" ); QUERY->add_arg( QUERY, "float", "x" ); // log QUERY->add_sfun( QUERY, log_impl, "float", "log" ); QUERY->add_arg( QUERY, "float", "x" ); // log2 QUERY->add_sfun( QUERY, log2_impl, "float", "log2" ); QUERY->add_arg( QUERY, "float", "x" ); // log10 QUERY->add_sfun( QUERY, log10_impl, "float", "log10" ); QUERY->add_arg( QUERY, "float", "x" ); // floor QUERY->add_sfun( QUERY, floor_impl, "float", "floor" ); QUERY->add_arg( QUERY, "float", "x" ); // ceil QUERY->add_sfun( QUERY, ceil_impl, "float", "ceil" ); QUERY->add_arg( QUERY, "float", "x" ); // round QUERY->add_sfun( QUERY, round_impl, "float", "round" ); QUERY->add_arg( QUERY, "float", "x" ); // trunc QUERY->add_sfun( QUERY, trunc_impl, "float", "trunc" ); QUERY->add_arg( QUERY, "float", "x" ); // fmod QUERY->add_sfun( QUERY, fmod_impl, "float", "fmod" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // remainder QUERY->add_sfun( QUERY, remainder_impl, "float", "remainder" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // min QUERY->add_sfun( QUERY, min_impl, "float", "min" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // max //! see \example powerup.ck QUERY->add_sfun( QUERY, max_impl, "float", "max" ); QUERY->add_arg( QUERY, "float", "x" ); QUERY->add_arg( QUERY, "float", "y" ); // isinf QUERY->add_sfun( QUERY, isinf_impl, "int", "isinf" ); QUERY->add_arg( QUERY, "float", "x" ); // isnan QUERY->add_sfun( QUERY, isnan_impl, "int", "isnan" ); QUERY->add_arg( QUERY, "float", "x" ); // nextpow2 QUERY->add_sfun( QUERY, nextpow2_impl, "int", "nextpow2" ); QUERY->add_arg( QUERY, "int", "n" ); // rand QUERY->add_sfun( QUERY, rand_impl, "int", "rand" ); //! return int between 0 and RAND_MAX // rand2 QUERY->add_sfun( QUERY, rand2_impl, "int", "rand2" ); //! integer between [min,max] QUERY->add_arg( QUERY, "int", "min" ); QUERY->add_arg( QUERY, "int", "max" ); // randf QUERY->add_sfun( QUERY, randf_impl, "float", "randf" ); //! rand between -1.0,1.0 // rand2f QUERY->add_sfun( QUERY, rand2f_impl, "float", "rand2f" ); //! rand between min and max QUERY->add_arg( QUERY, "float", "min" ); QUERY->add_arg( QUERY, "float", "max" ); // add mtof //! see \example mand-o-matic.ck QUERY->add_sfun( QUERY, mtof_impl, "float", "mtof" ); //! midi note to frequency QUERY->add_arg( QUERY, "float", "value" ); // add ftom QUERY->add_sfun( QUERY, ftom_impl, "float", "ftom" ); //! frequency to midi note QUERY->add_arg( QUERY, "float", "value" ); // add powtodb QUERY->add_sfun( QUERY, powtodb_impl, "float", "powtodb" ); //! linear power to decibel QUERY->add_arg( QUERY, "float", "value" ); // add rmstodb QUERY->add_sfun( QUERY, rmstodb_impl, "float", "rmstodb" ); //! rms to decibel QUERY->add_arg( QUERY, "float", "value" ); // add dbtopow QUERY->add_sfun( QUERY, dbtopow_impl, "float", "dbtopow" ); //! decibel to linear QUERY->add_arg( QUERY, "float", "value" ); // add dbtorms QUERY->add_sfun( QUERY, dbtorms_impl, "float", "dbtorms" ); //! decibel to rms QUERY->add_arg( QUERY, "float", "value" ); // pi //! see \example math.ck QUERY->add_svar( QUERY, "float", "PI", TRUE, &g_pi ); // twopi QUERY->add_svar( QUERY, "float", "TWO_PI", TRUE, &g_twopi ); // e QUERY->add_svar( QUERY, "float", "E", TRUE, &g_e ); // done QUERY->end_class( QUERY ); return TRUE; } // sin CK_DLL_SFUN( sin_impl ) { RETURN->v_float = ::sin( GET_CK_FLOAT(ARGS) ); } // cos CK_DLL_SFUN( cos_impl ) { RETURN->v_float = ::cos( GET_CK_FLOAT(ARGS) ); } // tan CK_DLL_SFUN( tan_impl ) { RETURN->v_float = ::tan( GET_CK_FLOAT(ARGS) ); } // asin CK_DLL_SFUN( asin_impl ) { RETURN->v_float = ::asin( GET_CK_FLOAT(ARGS) ); } // acos CK_DLL_SFUN( acos_impl ) { RETURN->v_float = ::acos( GET_CK_FLOAT(ARGS) ); } // atan CK_DLL_SFUN( atan_impl ) { RETURN->v_float = ::atan( GET_CK_FLOAT(ARGS) ); } // atan2 CK_DLL_SFUN( atan2_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1 ); RETURN->v_float = ::atan2( x, y ); } // sinh CK_DLL_SFUN( sinh_impl ) { RETURN->v_float = ::sinh( GET_CK_FLOAT(ARGS) ); } // cosh CK_DLL_SFUN( cosh_impl ) { RETURN->v_float = ::cosh( GET_CK_FLOAT(ARGS) ); } // tanh CK_DLL_SFUN( tanh_impl ) { RETURN->v_float = ::tanh( GET_CK_FLOAT(ARGS) ); } // hypot CK_DLL_SFUN( hypot_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = ::hypot( x, y ); } // pow CK_DLL_SFUN( pow_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = ::pow( x, y ); } // sqrt CK_DLL_SFUN( sqrt_impl ) { RETURN->v_float = ::sqrt( GET_CK_FLOAT(ARGS) ); } // exp CK_DLL_SFUN( exp_impl ) { RETURN->v_float = ::exp( GET_CK_FLOAT(ARGS) ); } // log CK_DLL_SFUN( log_impl ) { RETURN->v_float = ::log( GET_CK_FLOAT(ARGS) ); } // log2 CK_DLL_SFUN( log2_impl ) { RETURN->v_float = ::log( GET_CK_FLOAT(ARGS) )/::log( 2.0 ); } // log10 CK_DLL_SFUN( log10_impl ) { RETURN->v_float = ::log10( GET_CK_FLOAT(ARGS) ); } // floor CK_DLL_SFUN( floor_impl ) { RETURN->v_float = ::floor( GET_CK_FLOAT(ARGS) ); } // ceil CK_DLL_SFUN( ceil_impl ) { RETURN->v_float = ::ceil( GET_CK_FLOAT(ARGS) ); } // round CK_DLL_SFUN( round_impl ) { RETURN->v_float = round( GET_CK_FLOAT(ARGS) ); } // trunc CK_DLL_SFUN( trunc_impl ) { RETURN->v_float = trunc( GET_CK_FLOAT(ARGS) ); } // fmod CK_DLL_SFUN( fmod_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = fmod( x, y ); } // remainder CK_DLL_SFUN( remainder_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = remainder( x, y ); } // min CK_DLL_SFUN( min_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = x < y ? x : y; } // max CK_DLL_SFUN( max_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); t_CKFLOAT y = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = x > y ? x : y; } // isinf CK_DLL_SFUN( isinf_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); #ifdef __PLATFORM_WIN32__ RETURN->v_int = !_finite( x ); #else RETURN->v_int = isinf( x ); #endif } // isnan CK_DLL_SFUN( isnan_impl ) { t_CKFLOAT x = GET_CK_FLOAT(ARGS); #ifdef __PLATFORM_WIN32__ RETURN->v_int = _isnan( x ); #else RETURN->v_int = isnan( x ); #endif } // nextpow2 - thanks to Niklas Werner, via music-dsp CK_DLL_SFUN( nextpow2_impl ) { t_CKINT x = GET_CK_INT(ARGS); t_CKINT xx = x; for( ; x &= x-1; xx = x ); RETURN->v_int = xx * 2; } chuck-1.2.0.8.dfsg/src/ulib_math.h0000644000175000017500000000446310600421721015251 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_math.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __ULIB_MATH_H__ #define __ULIB_MATH_H__ #include "chuck_dl.h" // query DLL_QUERY libmath_query( Chuck_DL_Query * QUERY ); // impl CK_DLL_SFUN( sin_impl ); CK_DLL_SFUN( cos_impl ); CK_DLL_SFUN( tan_impl ); CK_DLL_SFUN( cot_impl ); CK_DLL_SFUN( asin_impl ); CK_DLL_SFUN( acos_impl ); CK_DLL_SFUN( atan_impl ); CK_DLL_SFUN( atan2_impl ); CK_DLL_SFUN( sinh_impl ); CK_DLL_SFUN( cosh_impl ); CK_DLL_SFUN( tanh_impl ); CK_DLL_SFUN( hypot_impl ); CK_DLL_SFUN( pow_impl ); CK_DLL_SFUN( sqrt_impl ); CK_DLL_SFUN( exp_impl ); CK_DLL_SFUN( log_impl ); CK_DLL_SFUN( log2_impl ); CK_DLL_SFUN( log10_impl ); CK_DLL_SFUN( floor_impl ); CK_DLL_SFUN( ceil_impl ); CK_DLL_SFUN( round_impl ); CK_DLL_SFUN( trunc_impl ); CK_DLL_SFUN( fmod_impl ); CK_DLL_SFUN( remainder_impl ); CK_DLL_SFUN( min_impl ); CK_DLL_SFUN( max_impl ); CK_DLL_SFUN( isinf_impl ); CK_DLL_SFUN( isnan_impl ); CK_DLL_SFUN( nextpow2_impl ); #endif chuck-1.2.0.8.dfsg/src/ulib_std.cpp0000644000175000017500000012021010600421721015432 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_std.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "ulib_std.h" #include #include #include #include "util_buffers.h" #include "util_console.h" #include "util_math.h" #include "util_string.h" #include "util_thread.h" #include "chuck_type.h" #include "chuck_instr.h" #if defined(__PLATFORM_WIN32__) #include int setenv( const char *n, const char *v, int i ) { return !SetEnvironmentVariable(n, v); } #else #include #endif // for ConsoleInput and StringTokenizer #include #include #include "util_thread.h" using namespace std; // KBHit CK_DLL_CTOR( KBHit_ctor ); CK_DLL_DTOR( KBHit_dtor ); CK_DLL_MFUN( KBHit_on ); CK_DLL_MFUN( KBHit_off ); CK_DLL_MFUN( KBHit_state ); CK_DLL_MFUN( KBHit_hit ); CK_DLL_MFUN( KBHit_more ); CK_DLL_MFUN( KBHit_getchar ); CK_DLL_MFUN( KBHit_can_wait ); static t_CKUINT KBHit_offset_data = 0; // Skot functions CK_DLL_CTOR( Skot_ctor ); CK_DLL_DTOR( Skot_dtor ); CK_DLL_MFUN( Skot_prompt ); CK_DLL_MFUN( Skot_prompt2 ); CK_DLL_MFUN( Skot_more ); CK_DLL_MFUN( Skot_getLine ); CK_DLL_MFUN( Skot_can_wait ); static t_CKUINT Skot_offset_data = 0; // StrTok functions CK_DLL_CTOR( StrTok_ctor ); CK_DLL_DTOR( StrTok_dtor ); CK_DLL_MFUN( StrTok_set ); CK_DLL_MFUN( StrTok_reset ); CK_DLL_MFUN( StrTok_more ); CK_DLL_MFUN( StrTok_next ); CK_DLL_MFUN( StrTok_next2 ); CK_DLL_MFUN( StrTok_get ); CK_DLL_MFUN( StrTok_get2 ); CK_DLL_MFUN( StrTok_size ); static t_CKUINT StrTok_offset_data = 0; #ifdef AJAY #include // VCR functions CK_DLL_CTOR( VCR_ctor ); CK_DLL_MFUN( VCR_load ); CK_DLL_MFUN( VCR_reset ); CK_DLL_MFUN( VCR_seek ); CK_DLL_MFUN( VCR_more ); CK_DLL_MFUN( VCR_curr ); CK_DLL_MFUN( VCR_next ); CK_DLL_MFUN( VCR_pos ); CK_DLL_MFUN( VCR_size ); CK_DLL_MFUN( VCR_name ); static t_CKUINT VCR_offset_data = 0; // Cereal functions CK_DLL_CTOR( Cereal_ctor ); CK_DLL_MFUN( Cereal_open ); CK_DLL_MFUN( Cereal_close ); CK_DLL_MFUN( Cereal_send ); CK_DLL_MFUN( Cereal_recv ); CK_DLL_MFUN( Cereal_more ); static t_CKUINT Cereal_offset_data = 0; #endif //----------------------------------------------------------------------------- // name: libstd_query() // desc: query entry point //----------------------------------------------------------------------------- DLL_QUERY libstd_query( Chuck_DL_Query * QUERY ) { // get global Chuck_Env * env = Chuck_Env::instance(); // set name QUERY->setname( QUERY, "Std" ); /*! \example std.rand2f( 100.0, 1000.0 ) => stdout; */ // register deprecate type_engine_register_deprecate( env, "std", "Std" ); // begin class QUERY->begin_class( QUERY, "Std", "Object" ); // add abs QUERY->add_sfun( QUERY, abs_impl, "int", "abs" ); QUERY->add_arg( QUERY, "int", "value" ); // add fabs QUERY->add_sfun( QUERY, fabs_impl, "float", "fabs" ); QUERY->add_arg( QUERY, "float", "value" ); // add rand QUERY->add_sfun( QUERY, rand_impl, "int", "rand"); //! return int between 0 and RAND_MAX // add rand2 QUERY->add_sfun( QUERY, rand2_impl, "int", "rand2" ); //! integer between [min,max] QUERY->add_arg( QUERY, "int", "min" ); QUERY->add_arg( QUERY, "int", "max" ); // add rand QUERY->add_sfun( QUERY, randf_impl, "float", "randf" ); //! rand between -1.0,1.0 // add rand2 QUERY->add_sfun( QUERY, rand2f_impl, "float", "rand2f" ); //! rand between min and max QUERY->add_arg( QUERY, "float", "min" ); QUERY->add_arg( QUERY, "float", "max" ); // add srand QUERY->add_sfun( QUERY, srand_impl, "void", "srand" ); QUERY->add_arg( QUERY, "int", "seed" ); // add sgn QUERY->add_sfun( QUERY, sgn_impl, "float", "sgn" ); //! return sign of value (-1, 0, 1) QUERY->add_arg( QUERY, "float", "value" ); // add system //! see \example std.ck QUERY->add_sfun( QUERY, system_impl, "int", "system" ); //! issue system command QUERY->add_arg( QUERY, "string", "cmd" ); // add atoi QUERY->add_sfun( QUERY, atoi_impl, "int", "atoi" ); //! string to integer QUERY->add_arg( QUERY, "string", "value" ); // add atof QUERY->add_sfun( QUERY, atof_impl, "float", "atof" ); //! string to float QUERY->add_arg( QUERY, "string", "value" ); // add itoa QUERY->add_sfun( QUERY, itoa_impl, "string", "itoa" ); //! int to string QUERY->add_arg( QUERY, "int", "i" ); // add ftoa QUERY->add_sfun( QUERY, ftoa_impl, "string", "ftoa" ); //! float to string QUERY->add_arg( QUERY, "float", "f" ); QUERY->add_arg( QUERY, "int", "precision" ); // add getenv QUERY->add_sfun( QUERY, getenv_impl, "string", "getenv" ); //! fetch environment variable QUERY->add_arg( QUERY, "string", "value" ); // add setenv QUERY->add_sfun( QUERY, setenv_impl, "int", "setenv" ); //! set environment variable QUERY->add_arg( QUERY, "string", "key" ); QUERY->add_arg( QUERY, "string", "value" ); // add mtof //! see \example mand-o-matic.ck QUERY->add_sfun( QUERY, mtof_impl, "float", "mtof" ); //! midi note to frequency QUERY->add_arg( QUERY, "float", "value" ); // add ftom QUERY->add_sfun( QUERY, ftom_impl, "float", "ftom" ); //! frequency to midi note QUERY->add_arg( QUERY, "float", "value" ); // add powtodb QUERY->add_sfun( QUERY, powtodb_impl, "float", "powtodb" ); //! linear power to decibel QUERY->add_arg( QUERY, "float", "value" ); // add rmstodb QUERY->add_sfun( QUERY, rmstodb_impl, "float", "rmstodb" ); //! rms to decibel QUERY->add_arg( QUERY, "float", "value" ); // add dbtopow QUERY->add_sfun( QUERY, dbtopow_impl, "float", "dbtopow" ); //! decibel to linear QUERY->add_arg( QUERY, "float", "value" ); // add dbtorms QUERY->add_sfun( QUERY, dbtorms_impl, "float", "dbtorms" ); //! decibel to rms QUERY->add_arg( QUERY, "float", "value" ); // finish class QUERY->end_class( QUERY ); // seed the rand srand( time( NULL ) ); Chuck_DL_Func * func = NULL; // KBHit // begin class (KBHit) if( !type_engine_import_class_begin( env, "KBHit", "Event", env->global(), KBHit_ctor, KBHit_dtor ) ) return FALSE; // add member variable KBHit_offset_data = type_engine_import_mvar( env, "int", "@KBHit_data", FALSE ); if( KBHit_offset_data == CK_INVALID_OFFSET ) goto error; // add on() func = make_new_mfun( "void", "on", KBHit_on ); if( !type_engine_import_mfun( env, func ) ) goto error; // add off() func = make_new_mfun( "void", "off", KBHit_off ); if( !type_engine_import_mfun( env, func ) ) goto error; // add state() func = make_new_mfun( "void", "state", KBHit_state ); if( !type_engine_import_mfun( env, func ) ) goto error; // add hit() func = make_new_mfun( "Event", "hit", KBHit_hit ); if( !type_engine_import_mfun( env, func ) ) goto error; // add more() func = make_new_mfun( "int", "more", KBHit_more ); if( !type_engine_import_mfun( env, func ) ) goto error; // add getchar() func = make_new_mfun( "int", "getchar", KBHit_getchar ); if( !type_engine_import_mfun( env, func ) ) goto error; // add can_wait() func = make_new_mfun( "int", "can_wait", KBHit_can_wait ); if( !type_engine_import_mfun( env, func ) ) goto error; // end class type_engine_import_class_end( env ); // start it KBHitManager::init(); // register deprecate type_engine_register_deprecate( env, "Skot", "ConsoleInput" ); // begin class (Skot) if( !type_engine_import_class_begin( env, "ConsoleInput", "Event", env->global(), Skot_ctor, Skot_dtor ) ) return FALSE; // add member variable Skot_offset_data = type_engine_import_mvar( env, "int", "@Skot_data", FALSE ); if( Skot_offset_data == CK_INVALID_OFFSET ) goto error; // add prompt() func = make_new_mfun( "Event", "prompt", Skot_prompt ); if( !type_engine_import_mfun( env, func ) ) goto error; // add prompt() func = make_new_mfun( "Event", "prompt", Skot_prompt2 ); func->add_arg( "string", "what" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add ready() func = make_new_mfun( "int", "more", Skot_more ); if( !type_engine_import_mfun( env, func ) ) goto error; // add getString() func = make_new_mfun( "string", "getLine", Skot_getLine ); if( !type_engine_import_mfun( env, func ) ) goto error; // add can_wait() func = make_new_mfun( "int", "can_wait", Skot_can_wait ); if( !type_engine_import_mfun( env, func ) ) goto error; // end class type_engine_import_class_end( env ); // register deprecate type_engine_register_deprecate( env, "PRC", "StringTokenizer" ); // begin class (StrTok) if( !type_engine_import_class_begin( env, "StringTokenizer", "Object", env->global(), StrTok_ctor, StrTok_dtor ) ) return FALSE; // add member variable StrTok_offset_data = type_engine_import_mvar( env, "int", "@StrTok_data", FALSE ); if( StrTok_offset_data == CK_INVALID_OFFSET ) goto error; // add set() func = make_new_mfun( "void", "set", StrTok_set ); func->add_arg( "string", "line" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add reset() func = make_new_mfun( "void", "reset", StrTok_reset ); if( !type_engine_import_mfun( env, func ) ) goto error; // add more() func = make_new_mfun( "int", "more", StrTok_more ); if( !type_engine_import_mfun( env, func ) ) goto error; // add next() func = make_new_mfun( "string", "next", StrTok_next ); if( !type_engine_import_mfun( env, func ) ) goto error; // add get() func = make_new_mfun( "string", "next", StrTok_next2 ); func->add_arg( "string", "out" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add get() func = make_new_mfun( "string", "get", StrTok_get ); func->add_arg( "int", "index" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add get() func = make_new_mfun( "string", "get", StrTok_get2 ); func->add_arg( "int", "index" ); func->add_arg( "string", "out" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add size() func = make_new_mfun( "int", "size", StrTok_size ); if( !type_engine_import_mfun( env, func ) ) goto error; // end class type_engine_import_class_end( env ); #ifdef AJAY // begin class // init base class if( !type_engine_import_class_begin( env, "VCR", "Object", env->global(), VCR_ctor ) ) return FALSE; // add member variable VCR_offset_data = type_engine_import_mvar( env, "int", "@me", FALSE ); if( VCR_offset_data == CK_INVALID_OFFSET ) goto error; // add load() func = make_new_mfun( "int", "load", VCR_load ); func->add_arg( "string", "filename" ); func->add_arg( "int", "column" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add reset() func = make_new_mfun( "int", "reset", VCR_reset ); if( !type_engine_import_mfun( env, func ) ) goto error; // add seek() func = make_new_mfun( "int", "seek", VCR_seek ); func->add_arg( "int", "where" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add more() func = make_new_mfun( "int", "more", VCR_more ); if( !type_engine_import_mfun( env, func ) ) goto error; // add curr() func = make_new_mfun( "float", "curr", VCR_curr ); if( !type_engine_import_mfun( env, func ) ) goto error; // add next() func = make_new_mfun( "int", "next", VCR_next ); if( !type_engine_import_mfun( env, func ) ) goto error; // add pos() func = make_new_mfun( "int", "pos", VCR_pos ); if( !type_engine_import_mfun( env, func ) ) goto error; // add size() func = make_new_mfun( "int", "size", VCR_size ); if( !type_engine_import_mfun( env, func ) ) goto error; // add name() func = make_new_mfun( "string", "name", VCR_name ); if( !type_engine_import_mfun( env, func ) ) goto error; // end the class import type_engine_import_class_end( env ); #if defined(__PLATFORM_WIN32__) // begin class (Cereal) if( !type_engine_import_class_begin( env, "Cereal", "Object", env->global(), Cereal_ctor ) ) return FALSE; // add member Cereal_offset_data = type_engine_import_mvar( env, "int", "@Cereal_data", FALSE ); if( Cereal_offset_data == CK_INVALID_OFFSET ) goto error; // add open() func = make_new_mfun( "int", "open", Cereal_open ); func->add_arg( "string", "name" ); func->add_arg( "int", "baudrate" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add close() func = make_new_mfun( "void", "close", Cereal_close ); if( !type_engine_import_mfun( env, func ) ) goto error; // add more() func = make_new_mfun( "int", "more", Cereal_more ); if( !type_engine_import_mfun( env, func ) ) goto error; // add send() func = make_new_mfun( "int", "send", Cereal_send ); func->add_arg( "int", "bite" ); if( !type_engine_import_mfun( env, func ) ) goto error; // add recv() func = make_new_mfun( "int", "recv", Cereal_recv ); if( !type_engine_import_mfun( env, func ) ) goto error; // end class type_engine_import_class_end( env ); #endif return TRUE; #else return TRUE; #endif error: // end the class import type_engine_import_class_end( env ); return FALSE; } #define RAND_INV_RANGE(r) (RAND_MAX / (r)) int irand_exclusive ( int max ) { int x = ::rand(); while (x >= max * RAND_INV_RANGE (max)) x = ::rand(); x /= RAND_INV_RANGE (max); return x; } // abs CK_DLL_SFUN( abs_impl ) { t_CKINT v = GET_CK_INT(ARGS); RETURN->v_int = v >= 0 ? v : -v; } // fabs CK_DLL_SFUN( fabs_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = v >= 0.0 ? v : -v; //RETURN->v_float = ::fabs( GET_CK_FLOAT(ARGS) ); } // rand CK_DLL_SFUN( rand_impl ) { RETURN->v_int = ::rand(); } // randf CK_DLL_SFUN( randf_impl ) { RETURN->v_float = ( 2.0 * ::rand() / (t_CKFLOAT)RAND_MAX - 1.0 ); } // randf CK_DLL_SFUN( rand2f_impl ) { t_CKFLOAT min = GET_CK_FLOAT(ARGS), max = *((t_CKFLOAT *)ARGS + 1); RETURN->v_float = min + (max-min)*(::rand()/(t_CKFLOAT)RAND_MAX); } // randi CK_DLL_SFUN( rand2_impl ) // inclusive. { int min = *(int *)ARGS, max = *((int *)ARGS + 1); int range = max - min; if ( range == 0 ) { RETURN->v_int = min; } //else if ( range < RAND_MAX / 2 ) { // RETURN->v_int = ( range > 0 ) ? min + irand_exclusive(1 + range) : max + irand_exclusive ( -range + 1 ) ; //} else { if( range > 0 ) { RETURN->v_int = min + (int) ( (1.0 + range) * ( ::rand()/(RAND_MAX+1.0) ) ); } else { RETURN->v_int = min - (int) ( (-range + 1.0) * ( ::rand()/(RAND_MAX+1.0) ) ); } } } // srand CK_DLL_SFUN( srand_impl ) { t_CKINT seed = GET_CK_INT(ARGS); ::srand( seed ); } // sgn CK_DLL_SFUN( sgn_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = v == 0.0f ? 0.0f : ( v > 0.0f ? 1.0f : -1.0f ); } // system CK_DLL_SFUN( system_impl ) { const char * cmd = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_int = system( cmd ); } // aoti CK_DLL_SFUN( atoi_impl ) { Chuck_String * str = GET_CK_STRING(ARGS); if( str ) { const char * v = str->str.c_str(); RETURN->v_int = atoi( v ); } else { RETURN->v_int = 0; } } // atof CK_DLL_SFUN( atof_impl ) { Chuck_String * str = GET_CK_STRING(ARGS); if( str ) { const char * v = GET_CK_STRING(ARGS)->str.c_str(); RETURN->v_float = atof( v ); } else { RETURN->v_float = 0.0; } } // itoa CK_DLL_SFUN( itoa_impl ) { t_CKINT i = GET_CK_INT(ARGS); // TODO: memory leak, please fix. Thanks. Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); a->str = itoa( i ); RETURN->v_string = a; } // ftoa CK_DLL_SFUN( ftoa_impl ) { t_CKFLOAT f = GET_NEXT_FLOAT(ARGS); t_CKINT p = GET_NEXT_INT(ARGS); Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); a->str = ftoa( f, (t_CKUINT)p ); RETURN->v_string = a; } // getenv static Chuck_String g_str; // PROBLEM: not thread friendly CK_DLL_SFUN( getenv_impl ) { const char * v = GET_CK_STRING(ARGS)->str.c_str(); const char * s = getenv( v ); Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); a->str = s ? s : ""; RETURN->v_string = a; } // setenv CK_DLL_SFUN( setenv_impl ) { const char * v1 = GET_NEXT_STRING(ARGS)->str.c_str(); const char * v2 = GET_NEXT_STRING(ARGS)->str.c_str(); RETURN->v_int = setenv( v1, v2, 1 ); } // mtof CK_DLL_SFUN( mtof_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = mtof(v); } // ftom CK_DLL_SFUN( ftom_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = ftom(v); } // powtodb CK_DLL_SFUN( powtodb_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = powtodb(v); } // rmstodb CK_DLL_SFUN( rmstodb_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = rmstodb(v); } // dbtopow CK_DLL_SFUN( dbtopow_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = dbtopow(v); } // dbtorms CK_DLL_SFUN( dbtorms_impl ) { t_CKFLOAT v = GET_CK_FLOAT(ARGS); RETURN->v_float = dbtorms(v); } // static CBufferAdvance * KBHitManager::the_buf = NULL; t_CKINT KBHitManager::the_onoff = 0; t_CKBOOL KBHitManager::the_init = FALSE; XThread * KBHitManager::the_thread; #define BUFFER_SIZE 1024 #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) static void * kb_loop( void * ) #else static unsigned int __stdcall kb_loop( void * ) #endif { t_CKINT c; EM_log( CK_LOG_INFO, "starting kb loop..." ); // go while( KBHitManager::the_init ) { // if on if( KBHitManager::the_onoff ) { // see if we have kb hit while( kb_hit() ) { // get the next char c = kb_getch(); // queue it KBHitManager::the_buf->put( &c, 1 ); } } // wait usleep( 5000 ); } return 0; } // init t_CKBOOL KBHitManager::init() { // sanity check if( the_buf ) return FALSE; EM_log( CK_LOG_INFO, "initializing KBHitManager..." ); the_buf = new CBufferAdvance; if( !the_buf->initialize( BUFFER_SIZE, sizeof(t_CKINT) ) ) { EM_log( CK_LOG_SEVERE, "KBHitManager: couldn't allocate central KB buffer..." ); SAFE_DELETE( the_buf ); return FALSE; } the_onoff = 0; the_init = TRUE; the_thread = new XThread; the_thread->start( kb_loop, NULL ); return TRUE; } // shutdown void KBHitManager::shutdown() { EM_log( CK_LOG_INFO, "shutting down KBHitManager..." ); SAFE_DELETE( the_buf ); kb_endwin(); the_onoff = 0; the_init = FALSE; } // on() void KBHitManager::on() { the_onoff++; if( !kb_ready() ) kb_initscr(); } // off() void KBHitManager::off() { the_onoff--; if( kb_ready() && the_onoff == 0 ) kb_endwin(); } // open() t_CKBOOL KBHitManager::open( KBHit * kb ) { if( the_buf == NULL ) return FALSE; if( kb->m_buffer != NULL ) return FALSE; EM_log( CK_LOG_INFO, "adding KBHit..." ); // init the kb kb->m_buffer = the_buf; // read index kb->m_read_index = kb->m_buffer->join( (Chuck_Event *)kb->SELF ); return TRUE; } // close() t_CKBOOL KBHitManager::close( KBHit * kb ) { if( the_buf == NULL ) return FALSE; if( kb->m_buffer == NULL ) return FALSE; EM_log( CK_LOG_INFO, "removing KBHit..." ); // unjoin kb->m_buffer->resign( kb->m_read_index ); // done kb->m_read_index = 0; return TRUE; } // KBHit KBHit::KBHit() { m_buffer = NULL; m_read_index = 0; m_valid = FALSE; m_onoff = FALSE; m_echo = FALSE; SELF = NULL; } // ~KBHit() KBHit::~KBHit() { this->close(); } // open() t_CKBOOL KBHit::open() { return KBHitManager::open( this ); } // close() t_CKBOOL KBHit::close() { return KBHitManager::close( this ); } // on() void KBHit::on() { if( m_onoff == FALSE ) { KBHitManager::on(); open(); m_onoff = TRUE; } } // off() void KBHit::off() { if( m_onoff == TRUE ) { KBHitManager::off(); open(); m_onoff = FALSE; } } // empty t_CKBOOL KBHit::empty() { if( m_buffer == NULL ) return TRUE; if( m_onoff == FALSE ) return TRUE; // if( m_read_index == 0 ) return TRUE; return m_buffer->empty( m_read_index ); } // getch t_CKINT KBHit::getch() { t_CKINT c; if( empty() ) return 0; m_buffer->get( &c, 1, m_read_index ); return c; } // ctor CK_DLL_CTOR( KBHit_ctor ) { KBHit * kb = new KBHit; OBJ_MEMBER_INT(SELF, KBHit_offset_data) = (t_CKINT)kb; kb->SELF = SELF; kb->on(); } // dtor CK_DLL_DTOR( KBHit_dtor ) { delete (KBHit *)OBJ_MEMBER_INT(SELF, KBHit_offset_data); OBJ_MEMBER_INT(SELF, KBHit_offset_data) = 0; } // on CK_DLL_MFUN( KBHit_on ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); kb->on(); } // off CK_DLL_MFUN( KBHit_off ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); kb->off(); } // state CK_DLL_MFUN( KBHit_state ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); RETURN->v_int = kb->state(); } // hit CK_DLL_MFUN( KBHit_hit ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); RETURN->v_object = SELF; } // more CK_DLL_MFUN( KBHit_more ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); RETURN->v_int = (kb->empty() == FALSE); } // getchar CK_DLL_MFUN( KBHit_getchar ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); RETURN->v_int = kb->getch(); } // can wait CK_DLL_MFUN( KBHit_can_wait ) { KBHit * kb = (KBHit *)(OBJ_MEMBER_INT(SELF, KBHit_offset_data)); RETURN->v_int = kb->empty(); } class LineEvent : public Chuck_Event { public: LineEvent( Chuck_Event * SELF ); ~LineEvent(); public: void prompt( const string & what = "" ); t_CKBOOL more(); string getLine(); t_CKBOOL can_wait(); void enqueue( const string & line ) { m_q.push( line ); } Chuck_Event * SELF; protected: queue m_q; }; // global variables t_CKBOOL g_le_launched = FALSE; t_CKBOOL g_le_wait = TRUE; // CHUCK_THREAD g_tid_le = 0; extern CHUCK_THREAD g_tid_whatever; map g_le_map; XMutex g_le_mutex; string g_le_what; extern Chuck_VM * g_vm; void * le_cb( void * p ) { char line[2048]; map::iterator iter; LineEvent * le = NULL; // loop while( true ) { // wait while( g_le_wait ) usleep( 10000 ); // check if( !g_vm ) break; // do the prompt cout << g_le_what; cout.flush(); if( !cin.getline( line, 2048 ) ) break; // lock g_le_mutex.acquire(); // go through for( iter = g_le_map.begin(); iter != g_le_map.end(); iter++ ) { // get the line event le = (*iter).first; // add to its queue le->enqueue( line ); // broadcast it le->SELF->queue_broadcast(); } // unlock g_le_mutex.release(); // reset wait g_le_wait = TRUE; } return NULL; } LineEvent::LineEvent( Chuck_Event * SELF ) { // launch the cb if( !g_le_launched ) { #if !defined(__PLATFORM_WIN32__) || defined(__WINDOWS_PTHREAD__) pthread_create( &g_tid_whatever, NULL, le_cb, NULL ); #else g_tid_whatever = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)le_cb, NULL, 0, 0 ); #endif g_le_launched = TRUE; } // lock g_le_mutex.acquire(); // add g_le_map[this] = this; this->SELF = SELF; // unlock g_le_mutex.release(); } LineEvent::~LineEvent() { // do nothing } void LineEvent::prompt( const string & what ) { // set what g_le_what = what; if( g_le_what != "" ) g_le_what += " "; // signal g_le_wait = FALSE; } t_CKBOOL LineEvent::more() { // more return m_q.size() > 0; } string LineEvent::getLine() { string ret; // lock g_le_mutex.acquire(); // get next line if( m_q.size() ) { // get it ret = m_q.front(); // dequeue it m_q.pop(); } else { ret = "[ERROR -> getLine() called on empty Skot]"; } // unlock g_le_mutex.release(); return ret; } t_CKBOOL LineEvent::can_wait() { return !more(); } // Skot CK_DLL_CTOR( Skot_ctor ) { LineEvent * le = new LineEvent((Chuck_Event *)SELF); OBJ_MEMBER_INT(SELF, Skot_offset_data) = (t_CKINT)le; } CK_DLL_DTOR( Skot_dtor ) { delete (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); OBJ_MEMBER_INT(SELF, Skot_offset_data) = 0; } CK_DLL_MFUN( Skot_prompt ) { LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); le->prompt(); RETURN->v_int = (t_CKINT)(SELF); } CK_DLL_MFUN( Skot_prompt2 ) { LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); const char * v = GET_CK_STRING(ARGS)->str.c_str(); le->prompt( v ); RETURN->v_int = (t_CKINT)(SELF); } CK_DLL_MFUN( Skot_more ) { LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); RETURN->v_int = le->more(); } CK_DLL_MFUN( Skot_getLine ) { LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); // TODO: memory leak Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); a->str = le->getLine(); RETURN->v_string = a; } CK_DLL_MFUN( Skot_can_wait ) { LineEvent * le = (LineEvent *)OBJ_MEMBER_INT(SELF, Skot_offset_data); RETURN->v_int = le->can_wait(); } // StrTok class StrTok { public: StrTok(); ~StrTok(); public: void set( const string & line ); void reset(); t_CKBOOL more(); string next(); string get( t_CKINT index ); t_CKINT size(); protected: istringstream * m_ss; string m_next; vector m_tokens; vector::size_type m_index; }; StrTok::StrTok() { m_ss = NULL; m_index = 0; } StrTok::~StrTok() { SAFE_DELETE( m_ss ); } void StrTok::set( const string & line ) { string s; // delete SAFE_DELETE( m_ss ); // alloc m_ss = new istringstream( line ); // read reset(); m_tokens.clear(); while( (*m_ss) >> s ) m_tokens.push_back( s ); } void StrTok::reset() { m_index = 0; } t_CKBOOL StrTok::more() { return m_index < m_tokens.size(); } string StrTok::next() { if( !more() ) return ""; return m_tokens[m_index++]; } string StrTok::get( t_CKINT index ) { if( index >= (t_CKINT)m_tokens.size() ) return ""; return m_tokens[index]; } t_CKINT StrTok::size() { return (t_CKINT)m_tokens.size(); } CK_DLL_CTOR( StrTok_ctor ) { StrTok * tokens = new StrTok; OBJ_MEMBER_INT(SELF, StrTok_offset_data) = (t_CKINT)tokens; } CK_DLL_DTOR( StrTok_dtor ) { delete (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); OBJ_MEMBER_INT(SELF, StrTok_offset_data) = 0; } CK_DLL_MFUN( StrTok_set ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); Chuck_String * s = GET_CK_STRING(ARGS); if( s ) tokens->set( s->str ); else tokens->set( "" ); } CK_DLL_MFUN( StrTok_reset ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); tokens->reset(); } CK_DLL_MFUN( StrTok_more ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); RETURN->v_int = (t_CKINT)tokens->more(); } CK_DLL_MFUN( StrTok_next ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); a->str = tokens->next(); RETURN->v_string = a; } CK_DLL_MFUN( StrTok_next2 ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); Chuck_String * a = GET_CK_STRING(ARGS); string s = tokens->next(); if( a ) a->str = s; RETURN->v_string = a; } CK_DLL_MFUN( StrTok_get ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); t_CKINT index = GET_NEXT_INT(ARGS); Chuck_String * a = (Chuck_String *)instantiate_and_initialize_object( &t_string, NULL ); string s = tokens->get( index ); a->str = s; RETURN->v_string = a; } CK_DLL_MFUN( StrTok_get2 ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); t_CKINT index = GET_NEXT_INT(ARGS); Chuck_String * a = GET_NEXT_STRING(ARGS); string s = tokens->get( index ); if( a ) a->str = s; RETURN->v_string = a; } CK_DLL_MFUN( StrTok_size ) { StrTok * tokens = (StrTok *)OBJ_MEMBER_INT(SELF, StrTok_offset_data); RETURN->v_int = tokens->size(); } #ifdef AJAY class ColumnReader { public: ColumnReader(); virtual ~ColumnReader(); bool init( const string & filename, long col ); bool reset() { if( !fin.good() ) return false; where = 0; return true; } bool seek( long pos ) { if( pos < 0 || pos >= values.size() ) return false; where = pos; return true; } bool more() { return where < values.size(); } double curr(); bool next() { if( where < values.size() ) where++; return more(); } long pos() { return where; } long size() { return values.size(); } string name() { return n; } Chuck_String s; protected: bool get_str( string & out ); bool get_double( double & out ); protected: ifstream fin; string n; long column; long where; char line[0x1000]; long len; vector values; }; ColumnReader::ColumnReader() { n = "[NONE]"; column = -1; where = -1; len = 0x1000; } ColumnReader::~ColumnReader() { // close file if( fin.good() ) fin.close(); } bool ColumnReader::init( const string & filename, long col ) { // hmm if( col < 1 ) { cerr << "column must be greater than 0!!!" << endl; return false; } // open file fin.open( filename.c_str(), ios::in ); // yes if( !fin.good() ) { cerr << "ColumnReader: cannot open file: '" << filename << "'..." << endl; return false; } // set column column = col; // read first line if( !fin.getline( line, len ) ) { cerr << "ColumnReader: cannot read first line: '" << filename << "'..." << endl; return false; } // get the name if( !get_str( n ) ) { cerr << "ColumnReader: cannot seek to column " << col << ": " << filename << "..." << endl; return false; } double v; long i = 1; // read values while( fin.getline( line, len ) ) { v = 0.0; // get value if( !get_double( v ) ) { cerr << "ColumnReader: cannot read column " << v << " on line i: " << n << "..." << endl; return false; } values.push_back( v ); } // well if( values.size() == 0 ) { cerr << "ColumnReader: file doesn't not contain data after first line: " << n << "..." << endl; return false; } // set location where = 0; s.str = n; return true; } double ColumnReader::curr() { if( where >= values.size() ) { cerr << "ColumnReader: trying to read beyond end of file: " << n << "..." << endl; return 0.0; } return values[where]; } bool ColumnReader::get_double( double & out ) { assert( column > 0 ); long c = 1; char * start = line; char * curr = start; while( c < column ) { // move past value while( *curr && *curr != ',' ) curr++; // move past , while( *curr && *curr == ',' ) curr++; // check if( *curr == '\0' ) { cerr << "ColumnReader: cannot find column " << column << ": " << n << endl; return false; } // increment c++; // set start start = curr; } // move past value while( *curr && *curr != ',' ) curr++; // end *curr = '\0'; out = atof( start ); return true; } bool ColumnReader::get_str( string & out ) { assert( column > 0 ); long c = 1; char * start = line; char * curr = start; while( c < column ) { // move past value while( *curr && *curr != ',' ) curr++; // move past , while( *curr && *curr == ',' ) curr++; // check if( *curr == '\0' ) { cerr << "ColumnReader: cannot find column " << column << ": " << n << endl; return false; } // increment c++; // set start start = curr; } // move past value while( *curr && *curr != ',' ) curr++; // end *curr = '\0'; out = start; return true; } CK_DLL_CTOR( VCR_ctor ) { OBJ_MEMBER_INT(SELF, VCR_offset_data) = (t_CKUINT)new ColumnReader; } CK_DLL_MFUN( VCR_load ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); const char * filename = GET_NEXT_STRING(ARGS)->str.c_str(); t_CKINT column = GET_NEXT_INT(ARGS); RETURN->v_int = vcr->init( filename, column ); } CK_DLL_MFUN( VCR_reset ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_int = vcr->reset(); } CK_DLL_MFUN( VCR_seek ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); t_CKINT where = GET_CK_INT(ARGS); RETURN->v_int = vcr->seek( where ); } CK_DLL_MFUN( VCR_more ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_int = vcr->more(); } CK_DLL_MFUN( VCR_curr ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_float = vcr->curr(); } CK_DLL_MFUN( VCR_next ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_int = vcr->next(); } CK_DLL_MFUN( VCR_pos ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_int = vcr->pos(); } CK_DLL_MFUN( VCR_size ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_int = vcr->size(); } CK_DLL_MFUN( VCR_name ) { ColumnReader * vcr = (ColumnReader*)OBJ_MEMBER_INT(SELF, VCR_offset_data); RETURN->v_string = &(vcr->s); } #ifdef __PLATFORM_WIN32__ // jeff's cereal class Serial { public: // one stop bit, 8 bits, no parity Serial(); ~Serial(); unsigned read( char * buffer, unsigned numberOfBytesToRead ); unsigned write( char * buffer, unsigned numberOfBytesToWrite ); void write( char c ); char read(); unsigned available() const; t_CKBOOL open( char * port, t_CKUINT baudrate ); void close(); private: HANDLE serialFile; }; Serial::Serial( ) { serialFile = NULL; } Serial::~Serial( ) { close(); } t_CKBOOL Serial::open( char * port, t_CKUINT baudrate ) { if( serialFile ) close(); // open port serialFile = CreateFile( port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 ); if( serialFile == INVALID_HANDLE_VALUE ) { if( GetLastError() == ERROR_FILE_NOT_FOUND ) { EM_log( CK_LOG_SYSTEM, "error: cannot open serial port '%s'...", port ); } else { EM_log( CK_LOG_SYSTEM, "error opening serial port '%s'...", port ); } return FALSE; } // set params DCB dcbSerialParams = {0}; dcbSerialParams.DCBlength = sizeof( dcbSerialParams ); if( !GetCommState( serialFile, &dcbSerialParams) ) { EM_log( CK_LOG_SYSTEM, "error getting serial state..." ); close(); return FALSE; } dcbSerialParams.BaudRate = baudrate; dcbSerialParams.ByteSize = 8; dcbSerialParams.StopBits = ONESTOPBIT; dcbSerialParams.Parity = NOPARITY; if( !SetCommState( serialFile, &dcbSerialParams ) ) { EM_log( CK_LOG_SYSTEM, "error setting serial state..." ); close(); return FALSE; } // SET TIMEOUTS /* COMMTIMEOUTS timeouts = {0}; timeouts.ReadIntervalTimeout = 50; timeouts.ReadTotalTimeoutConstant = 50; timeouts.ReadTotalTimeoutMultiplier = 10; timeouts.WriteTotalTimeoutConstant= 50; timeouts.WriteTotalTimeoutMultiplier = 10; if( !SetCommTimeouts( serialFile, &timeouts ) ) { //error occureed. Inform user } */ return TRUE; } void Serial::close() { if( serialFile ) { CloseHandle( serialFile ); serialFile = NULL; } } void Serial::write( char c ) { write( &c, 1 ); } char Serial::read() { char c = '\0'; read( &c, 1 ); return c; } unsigned Serial::available() const { struct _COMSTAT status; unsigned long etat; memset( &status, 0, sizeof(status) ); if( serialFile ) { ClearCommError( serialFile, &etat, &status); return status.cbInQue; } return 0; } // try to read numberOfBytesToRead into buffer, return how many bytes read unsigned Serial::read( char * buffer, unsigned numberOfBytesToRead ) { DWORD bytesRead = 0; if( serialFile ) ReadFile( serialFile, buffer, numberOfBytesToRead, &bytesRead, NULL ); return bytesRead; } // try to write numberOfBytesToWrite to serial from buffer, return how many bytes written unsigned Serial::write( char * buffer, unsigned numberOfBytesToWrite ) { DWORD bytesWritten = 0; if( serialFile ) WriteFile( serialFile, buffer, numberOfBytesToWrite, &bytesWritten, NULL ); return bytesWritten; } // ctor CK_DLL_CTOR( Cereal_ctor ) { OBJ_MEMBER_UINT(SELF, Cereal_offset_data) = (t_CKUINT)new Serial; } // open CK_DLL_MFUN( Cereal_open ) { Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data); Chuck_String * str = GET_NEXT_STRING(ARGS); t_CKINT i = GET_NEXT_INT(ARGS); // close s->close(); if( str ) RETURN->v_int = s->open( (char *)str->str.c_str(), i ); else RETURN->v_int = 0; } // close CK_DLL_MFUN( Cereal_close ) { Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data); s->close(); } // more CK_DLL_MFUN( Cereal_more ) { Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data); RETURN->v_int = s->available(); } // send CK_DLL_MFUN( Cereal_send ) { Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data); t_CKINT i = GET_NEXT_INT(ARGS); s->write( i ); RETURN->v_int = i; } // recv CK_DLL_MFUN( Cereal_recv ) { Serial * s = (Serial *)OBJ_MEMBER_UINT(SELF, Cereal_offset_data); if( s->available() ) RETURN->v_int = (t_CKINT)s->read(); else RETURN->v_int = 0; } #endif #endif chuck-1.2.0.8.dfsg/src/ulib_std.h0000644000175000017500000000674310600421720015114 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: ulib_std.h // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __ULIB_STD_H__ #define __ULIB_STD_H__ #include "chuck_dl.h" // query DLL_QUERY libstd_query( Chuck_DL_Query * QUERY ); // exports CK_DLL_SFUN( abs_impl ); CK_DLL_SFUN( fabs_impl ); CK_DLL_SFUN( rand_impl ); CK_DLL_SFUN( randf_impl ); CK_DLL_SFUN( rand2f_impl ); CK_DLL_SFUN( rand2_impl ); CK_DLL_SFUN( srand_impl ); CK_DLL_SFUN( sgn_impl ); CK_DLL_SFUN( system_impl ); CK_DLL_SFUN( atoi_impl ); CK_DLL_SFUN( atof_impl ); CK_DLL_SFUN( itoa_impl ); CK_DLL_SFUN( ftoa_impl ); CK_DLL_SFUN( getenv_impl ); CK_DLL_SFUN( setenv_impl ); CK_DLL_SFUN( mtof_impl ); CK_DLL_SFUN( ftom_impl ); CK_DLL_SFUN( powtodb_impl ); CK_DLL_SFUN( rmstodb_impl ); CK_DLL_SFUN( dbtopow_impl ); CK_DLL_SFUN( dbtorms_impl ); // forward reference class CBufferAdvance; struct ChucK_Object; struct XThread; //----------------------------------------------------------------------------- // name: class KBHit // desc: kbhit class //----------------------------------------------------------------------------- class KBHit : public Chuck_Event { public: KBHit(); ~KBHit(); public: t_CKBOOL open(); t_CKBOOL close(); void on(); void off(); t_CKBOOL good() { return m_valid; } t_CKBOOL state() { return m_onoff; } public: void set_echo( t_CKBOOL echo ) { m_echo = echo; } t_CKBOOL get_echo() { return m_echo; } public: t_CKBOOL empty(); t_CKINT getch(); public: CBufferAdvance * m_buffer; t_CKUINT m_read_index; t_CKBOOL m_valid; t_CKBOOL m_onoff; t_CKBOOL m_echo; Chuck_Object * SELF; }; //----------------------------------------------------------------------------- // name: class KBHitManager // desc: ... //----------------------------------------------------------------------------- class KBHitManager { public: static t_CKBOOL init(); static void shutdown(); static void on(); static void off(); static t_CKBOOL open( KBHit * kb ); static t_CKBOOL close( KBHit * kb ); public: static CBufferAdvance * the_buf; static t_CKINT the_onoff; static t_CKBOOL the_init; static XThread * the_thread; }; #endif chuck-1.2.0.8.dfsg/src/util_buffers.cpp0000644000175000017500000002720410600421720016326 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_buffers.cpp // desc: buffer implementation // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Spring 2004 // Summer 2005 - updated to allow many readers //----------------------------------------------------------------------------- #include #include "util_buffers.h" //----------------------------------------------------------------------------- // name: CBufferAdvance() // desc: constructor //----------------------------------------------------------------------------- CBufferAdvance::CBufferAdvance() { m_data = NULL; m_data_width = m_write_offset = m_max_elem = 0; // = m_read_offset } //----------------------------------------------------------------------------- // name: ~CBufferAdvance() // desc: destructor //----------------------------------------------------------------------------- CBufferAdvance::~CBufferAdvance() { this->cleanup(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize //----------------------------------------------------------------------------- BOOL__ CBufferAdvance::initialize( UINT__ num_elem, UINT__ width ) { // cleanup cleanup(); // allocate m_data = (BYTE__ *)malloc( num_elem * width ); if( !m_data ) return false; m_data_width = width; //m_read_offset = 0; m_write_offset = 0; m_max_elem = (SINT__)num_elem; return true; } //----------------------------------------------------------------------------- // name: cleanup() // desc: cleanup //----------------------------------------------------------------------------- void CBufferAdvance::cleanup() { if( !m_data ) return; free( m_data ); m_data = NULL; m_data_width = 0; m_write_offset = m_max_elem = 0; // = m_read_offset } //----------------------------------------------------------------------------- // name: UINT__ join() // desc: shred can call this to get an index into the vector of read pointers //----------------------------------------------------------------------------- UINT__ CBufferAdvance::join( Chuck_Event * event ) { // index of new pointer that will be pushed back UINT__ read_offset_index; // add new pointer pointing (as pointers do) to current write offset // (shreds don't get interrupted, so m_write_offset will always be correct, right?) // (uh, hope so...) if( !m_free.empty() ) { read_offset_index = m_free.front(); m_free.pop(); //assert( read_offset_index < m_read_offsets.size() ); m_read_offsets[read_offset_index] = ReadOffset( m_write_offset, event ); } else { read_offset_index = m_read_offsets.size(); m_read_offsets.push_back( ReadOffset( m_write_offset, event ) ); } // return index return read_offset_index; } //----------------------------------------------------------------------------- // name: resign // desc: shred quits buffer; frees its index //----------------------------------------------------------------------------- void CBufferAdvance::resign( UINT__ read_offset_index ) { // make sure read_offset_index passed in is valid if( read_offset_index < 0 || read_offset_index >= m_read_offsets.size() ) return; // add this index to free queue m_free.push( read_offset_index ); // "invalidate" the pointer at that index m_read_offsets[read_offset_index].read_offset = -1; } //----------------------------------------------------------------------------- // name: put() // desc: put //----------------------------------------------------------------------------- /*void CBufferAdvance::put( void * data, UINT__ num_elem ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { m_data[m_write_offset*m_data_width+j] = d[i*m_data_width+j]; } // move the write m_write_offset++; // wrap if( m_write_offset >= m_max_elem ) m_write_offset = 0; } }*/ void CBufferAdvance::put( void * data, UINT__ num_elem ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { m_data[m_write_offset*m_data_width+j] = d[i*m_data_width+j]; } // move the write m_write_offset++; // wrap if( m_write_offset >= m_max_elem ) m_write_offset = 0; // possibility of expelling evil shreds for( j = 0; j < m_read_offsets.size(); j++ ) { if( m_write_offset == m_read_offsets[j].read_offset ) { // inform shred with index j that it has lost its privileges? // invalidate its read_offset // m_read_offsets[j].read_offset = -1; } if( m_read_offsets[j].event ) m_read_offsets[j].event->queue_broadcast(); } } } //----------------------------------------------------------------------------- // name: get() // desc: get //----------------------------------------------------------------------------- /*UINT__ CBufferAdvance::get( void * data, UINT__ num_elem ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // read catch up with write if( m_read_offset == m_write_offset ) return 0; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { d[i*m_data_width+j] = m_data[m_read_offset*m_data_width+j]; } // move read m_read_offset++; // catch up if( m_read_offset == m_write_offset ) { i++; break; } // wrap if( m_read_offset >= m_max_elem ) m_read_offset = 0; } // return number of elems return 1; }*/ BOOL__ CBufferAdvance::empty( UINT__ read_offset_index ) { // make sure index is valid if( read_offset_index >= m_read_offsets.size() ) return TRUE; if( m_read_offsets[read_offset_index].read_offset < 0 ) return TRUE; SINT__ m_read_offset = m_read_offsets[read_offset_index].read_offset; // see if caught up return m_read_offset == m_write_offset; } UINT__ CBufferAdvance::get( void * data, UINT__ num_elem, UINT__ read_offset_index ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // make sure index is valid if( read_offset_index >= m_read_offsets.size() ) return 0; if( m_read_offsets[read_offset_index].read_offset < 0 ) return 0; SINT__ m_read_offset = m_read_offsets[read_offset_index].read_offset; // read catch up with write if( m_read_offset == m_write_offset ) return 0; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { d[i*m_data_width+j] = m_data[m_read_offset*m_data_width+j]; } // move read m_read_offset++; // catch up if( m_read_offset == m_write_offset ) { i++; break; } // wrap if( m_read_offset >= m_max_elem ) m_read_offset = 0; } // update read offset at given index m_read_offsets[read_offset_index].read_offset = m_read_offset; // return number of elems return i; } //----------------------------------------------------------------------------- // name: CBufferSimple() // desc: constructor //----------------------------------------------------------------------------- CBufferSimple::CBufferSimple() { m_data = NULL; m_data_width = m_read_offset = m_write_offset = m_max_elem = 0; } //----------------------------------------------------------------------------- // name: ~CBufferSimple() // desc: destructor //----------------------------------------------------------------------------- CBufferSimple::~CBufferSimple() { this->cleanup(); } //----------------------------------------------------------------------------- // name: initialize() // desc: initialize //----------------------------------------------------------------------------- BOOL__ CBufferSimple::initialize( UINT__ num_elem, UINT__ width ) { // cleanup cleanup(); // allocate m_data = (BYTE__ *)malloc( num_elem * width ); if( !m_data ) return false; m_data_width = width; m_read_offset = 0; m_write_offset = 0; m_max_elem = num_elem; return true; } //----------------------------------------------------------------------------- // name: cleanup() // desc: cleanup //----------------------------------------------------------------------------- void CBufferSimple::cleanup() { if( !m_data ) return; free( m_data ); m_data = NULL; m_data_width = m_read_offset = m_write_offset = m_max_elem = 0; } //----------------------------------------------------------------------------- // name: put() // desc: put //----------------------------------------------------------------------------- void CBufferSimple::put( void * data, UINT__ num_elem ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { m_data[m_write_offset*m_data_width+j] = d[i*m_data_width+j]; } // move the write m_write_offset++; // wrap if( m_write_offset >= m_max_elem ) m_write_offset = 0; } } //----------------------------------------------------------------------------- // name: get() // desc: get //----------------------------------------------------------------------------- UINT__ CBufferSimple::get( void * data, UINT__ num_elem ) { UINT__ i, j; BYTE__ * d = (BYTE__ *)data; // read catch up with write if( m_read_offset == m_write_offset ) return 0; // copy for( i = 0; i < num_elem; i++ ) { for( j = 0; j < m_data_width; j++ ) { d[i*m_data_width+j] = m_data[m_read_offset*m_data_width+j]; } // move read m_read_offset++; // catch up if( m_read_offset == m_write_offset ) { i++; break; } // wrap if( m_read_offset >= m_max_elem ) m_read_offset = 0; } // return number of elems return 1; // shouldn't it return i? } chuck-1.2.0.8.dfsg/src/util_buffers.h0000644000175000017500000000727310600421720015777 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_buffers.h // desc: buffer // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ananya Misra (amisra@cs.princeton.edu) // date: Spring 2004 // Summer 2005 - allow multiple readers //----------------------------------------------------------------------------- #ifndef __UTIL_BUFFERS_H__ #define __UTIL_BUFFERS_H__ #include "chuck_oo.h" #include #include #define DWORD__ unsigned long #define SINT__ long #define UINT__ DWORD__ #define BOOL__ DWORD__ #define BYTE__ unsigned char #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif //----------------------------------------------------------------------------- // name: class CBufferAdvance // desc: circular buffer //----------------------------------------------------------------------------- class CBufferAdvance { public: CBufferAdvance(); ~CBufferAdvance(); public: BOOL__ initialize( UINT__ num_elem, UINT__ width ); void cleanup(); public: UINT__ get( void * data, UINT__ num_elem, UINT__ read_offset_index ); void put( void * data, UINT__ num_elem ); BOOL__ empty( UINT__ read_offset_index ); UINT__ join( Chuck_Event * event = NULL ); void resign( UINT__ read_offset_index ); protected: BYTE__ * m_data; UINT__ m_data_width; //UINT__ m_read_offset; // this holds the offset allocated by join(), paired with an optional // Chuck_Event to notify when things are put in the buffer struct ReadOffset { SINT__ read_offset; Chuck_Event * event; ReadOffset( SINT__ ro, Chuck_Event * e = NULL ) { read_offset = ro; event = e; } }; std::vector m_read_offsets; std::queue m_free; SINT__ m_write_offset; SINT__ m_max_elem; }; //----------------------------------------------------------------------------- // name: class CBufferSimple // desc: circular buffer - one reader one writer //----------------------------------------------------------------------------- class CBufferSimple { public: CBufferSimple(); ~CBufferSimple(); public: BOOL__ initialize( UINT__ num_elem, UINT__ width ); void cleanup(); public: UINT__ get( void * data, UINT__ num_elem ); void put( void * data, UINT__ num_elem ); protected: BYTE__ * m_data; UINT__ m_data_width; UINT__ m_read_offset; UINT__ m_write_offset; UINT__ m_max_elem; }; #endif chuck-1.2.0.8.dfsg/src/util_console.cpp0000644000175000017500000001003210600421720016323 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_console.cpp // desc: ... // // author: Spencer Salazar (ssalazar@princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #include "util_console.h" #include "chuck_errmsg.h" #include #ifdef __USE_READLINE__ #include #else #include #define CONSOLE_INPUT_BUFFER_SIZE 255 #endif char * io_readline( const char * prompt ) { #ifdef __USE_READLINE__ // call the real readline return readline( prompt ); #else // insert our hack char * buf=(char *)malloc( CONSOLE_INPUT_BUFFER_SIZE * sizeof(char) ); char * result; fputs( prompt, stdout ); result = fgets( buf, CONSOLE_INPUT_BUFFER_SIZE, stdin ); if( result == NULL ) { free( buf ); return NULL; } for( int i=0; i < CONSOLE_INPUT_BUFFER_SIZE; i++ ) if(buf[i] == '\n' ) { buf[i] = 0; break; } return buf; #endif } void io_addhistory( const char * addme ) { #ifdef __USE_READLINE__ add_history( addme ); #else //do nothing #endif } // code thanks to Luke Lin (wdlin@CCCA.NCTU.edu.tw) // kb hit #ifndef __PLATFORM_WIN32__ #include #ifdef __PLATFORM_MACOSX__ #include static struct termios g_save; #else #include static struct termio g_save; #endif #include #include #else #include #endif // global static t_CKINT g_c; static t_CKBOOL g_init; // on entering mode t_CKBOOL kb_initscr() { if( g_init ) return FALSE; #ifndef __PLATFORM_WIN32__ #ifdef __PLATFORM_MACOSX__ struct termios term; if( ioctl( 0, TIOCGETA, &term ) == -1 ) #else struct termio term; if( ioctl( 0, TCGETA, &term ) == -1 ) #endif { EM_log( CK_LOG_SEVERE, "(kbhit disabled): standard input not a tty!"); return FALSE; } // log EM_log( CK_LOG_INFO, "starting kb hit immediate mode..." ); g_save = term; term.c_lflag &= ~ICANON; term.c_lflag &= ~ECHO; term.c_cc[VMIN] = 0; term.c_cc[VTIME]=0; #ifdef __PLATFORM_MACOSX__ ioctl( 0, TIOCSETA, &term ); #else ioctl( 0, TCSETA, &term ); #endif #endif g_init = TRUE; return TRUE; } // on exit void kb_endwin() { if( !g_init ) return; #ifndef __PLATFORM_WIN32__ #ifdef __PLATFORM_MACOSX__ ioctl( 0, TIOCSETA, &g_save ); #else ioctl( 0, TCSETA, &g_save ); #endif #endif g_init = FALSE; } // hit t_CKINT kb_hit() { #ifndef __PLATFORM_WIN32__ int ifkeyin; char c; ifkeyin = read( 0, &c, 1 ); g_c = (t_CKINT)c; // log EM_log( CK_LOG_FINE, "kb hit! %i : %c", ifkeyin, c ); return (ifkeyin); #else return (t_CKINT)kbhit(); #endif } // get t_CKINT kb_getch() { #ifndef __PLATFORM_WIN32__ return g_c; #else return (t_CKINT)::getch(); #endif } // ready t_CKBOOL kb_ready() { return g_init; } chuck-1.2.0.8.dfsg/src/util_console.h0000644000175000017500000000340310600421720015774 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_console.h // desc: utility for console I/O // // author: Spencer Salazar (ssalazar@princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // date: Autumn 2005 //----------------------------------------------------------------------------- #ifndef __UTIL_CONSOLE_H__ #define __UTIL_CONSOLE_H__ #include "chuck_def.h" // read a line char * io_readline( const char * ); // add a line to the history void io_addhistory( const char * ); // kb hit emulation t_CKBOOL kb_initscr(); void kb_endwin(); t_CKINT kb_hit(); t_CKINT kb_getch(); t_CKBOOL kb_ready(); #endif chuck-1.2.0.8.dfsg/src/util_hid.cpp0000644000175000017500000061334210600421720015442 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_hid.cpp // desc: refactored HID joystick, keyboard, mouse support // // author: Spencer Salazar (ssalazar@cs.princeton.edu) // date: summer 2006 //----------------------------------------------------------------------------- #include "chuck_def.h" #include "chuck_errmsg.h" #include "util_hid.h" #include "hidio_sdl.h" #include #include using namespace std; #ifdef __PLATFORM_MACOSX__ #pragma mark OS X General HID support /* TODO: *********************************************************************** Make Joystick/Mouse/Keyboard_open/_close thread safe (i.e., do all ->configure and ->startQueue calls on the Hid thread). *** DONE Make ->disconnect delete the element list *** worked around Make Keyboard, Mouse dis/reattachment work *** DONE *******************************************************************************/ #include #include #include #include #include #include #include #include #include #include // check for OS X 10.4/CGEvent #include #undef MAC_OS_X_VERSION_MIN_REQUIRED #undef MAC_OS_X_VERSION_MAX_ALLOWED #define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_3 #define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_4 #include #ifdef __CGEVENT_H__ #define __CK_HID_CURSOR_TRACK__ #endif #ifndef __DAN__ #undef __CK_HID_CURSOR_TRACK__ #endif #ifdef __CK_HID_WIIREMOTE__ #include #include "util_buffers.h" #endif // __CK_HID_WIIREMOTE__ class lockable { public: void lock() { m_mutex.acquire(); } void unlock() { m_mutex.release(); } private: XMutex m_mutex; }; template< typename _Tp, typename _Alloc = allocator< _Tp > > class xvector : public vector< _Tp, _Alloc >, public lockable { }; template , typename _Alloc = allocator > > class xmultimap : public multimap< _Key, _Tp, _Compare, _Alloc >, public lockable { }; class OSX_Device : public lockable { public: OSX_Device() { refcount = 0; } virtual ~OSX_Device() {} virtual void open() {}; virtual void close() {}; t_CKUINT refcount; // incremented on open, decremented on close }; class OSX_Hid_Device_Element { public: OSX_Hid_Device_Element() { cookie = 0; num = 0; value = 0; usage = usage_page = 0; min = 0; max = 0; } IOHIDElementCookie cookie; t_CKINT type; t_CKINT num; t_CKINT value; t_CKINT usage_page; t_CKINT usage; t_CKINT min; t_CKINT max; }; class OSX_Hid_Device : public OSX_Device { public: OSX_Hid_Device() { configed = preconfiged = FALSE; plugInInterface = NULL; interface = NULL; queue = NULL; strncpy( name, "Device", 256 ); elements = NULL; outputs = NULL; usage = usage_page = 0; type = num = -1; buttons = -1; axes = -1; hats = -1; wheels = -1; refcount = 0; hidProperties = NULL; removal_notification = NULL; vendorID = productID = locationID = NULL; manufacturer = product = NULL; } ~OSX_Hid_Device() { cleanup(); } t_CKINT preconfigure( io_object_t ioHIDDeviceObject ); t_CKINT configure(); void enumerate_elements( CFArrayRef cfElements ); t_CKINT start(); t_CKINT stop(); t_CKBOOL is_connected() const; t_CKBOOL is_same_as( io_object_t ioHIDDeviceObject ) const; void disconnect(); void cleanup(); IOCFPlugInInterface ** plugInInterface; IOHIDDeviceInterface ** interface; // device interface IOHIDQueueInterface ** queue; // device event queue char name[256]; // uniquely identifying information /* For ChucK's purposes, HID devices are uniquely identified by the tuple of (USB device location, vendor ID, product ID, manufacturer name, product name ) */ CFNumberRef locationID; CFNumberRef vendorID; CFNumberRef productID; CFStringRef manufacturer; CFStringRef product; t_CKBOOL preconfiged, configed; t_CKINT type; t_CKINT num; t_CKINT usage_page; t_CKINT usage; map< IOHIDElementCookie, OSX_Hid_Device_Element * > * elements; /* Note: setting any of these to -1 informs the element enumerating method that we are not interested in that particular element type */ t_CKINT buttons; t_CKINT axes; t_CKINT hats; t_CKINT wheels; /* outputs are stored in a map of vectors of OSX_Hid_Device_Elements Thus if ( *outputs )[CK_HID_OUTPUT_TYPE] != NULL && ( *outputs )[CK_HID_OUTPUT_TYPE]->size() > n, ( *outputs )[CK_HID_OUTPUT_TYPE]->at( n ) is the nth output of type CK_HID_OUTPUT_TYPE. */ map< unsigned int, vector< OSX_Hid_Device_Element * > * > * outputs; CFRunLoopSourceRef eventSource; CFMutableDictionaryRef hidProperties; io_object_t removal_notification; const static t_CKINT event_queue_size = 50; // queues use wired kernel memory so should be set to as small as possible // but should account for the maximum possible events in the queue // USB updates will likely occur at 100 Hz so one must account for this rate // if states change quickly (updates are only posted on state changes) }; struct OSX_Hid_op { enum { open, close } type; xvector< OSX_Hid_Device * > * v; xvector< OSX_Hid_Device * >::size_type index; }; #pragma mark global variables // hid run loop (event dispatcher) static CFRunLoopRef rlHid = NULL; // special hid run loop mode (limits events to hid device events only) //static const CFStringRef kCFRunLoopChuckHidMode = CFSTR( "ChucKHid" ); static const CFStringRef kCFRunLoopChuckHidMode = kCFRunLoopDefaultMode; // general hid callback for device events static void Hid_callback( void * target, IOReturn result, void * refcon, void * sender ); // CFRunLoop source for open/close device operations static CFRunLoopSourceRef hidOpSource = NULL; // cbuffer for open/close device operations static CBufferSimple * hid_operation_buffer = NULL; // callback for open/close device operations static void Hid_do_operation( void * info ); // IO iterator for new hid devices // we only keep track of this so we can release it later io_iterator_t hid_iterator = NULL; // notification port for device add/remove events static IONotificationPortRef newDeviceNotificationPort = NULL; // callback for new devices static void Hid_new_devices( void * refcon, io_iterator_t iterator ); // callback for device removal static void Hid_device_removed( void * refcon, io_service_t service, natural_t messageType, void * messageArgument ); /* the mutexes should be acquired whenever making changes to the corresponding vectors or accessing them from a non-hid thread after the hid thread has been started */ static xvector< OSX_Hid_Device * > * joysticks = NULL; static xvector< OSX_Hid_Device * > * mice = NULL; static xvector< OSX_Hid_Device * > * keyboards = NULL; static xmultimap< string, OSX_Hid_Device * > * joystick_names = NULL; static xmultimap< string, OSX_Hid_Device * > * mouse_names = NULL; static xmultimap< string, OSX_Hid_Device * > * keyboard_names = NULL; // has hid been initialized? static t_CKBOOL g_hid_init = FALSE; // table to translate keys to ASCII static t_CKBYTE g_hid_key_table[256]; // cursor track stuff #ifdef __CK_HID_CURSOR_TRACK__ static t_CKINT cursorX = 0; static t_CKINT cursorY = 0; static t_CKFLOAT scaledCursorX = 0; static t_CKFLOAT scaledCursorY = 0; static CFRunLoopRef rlCursorTrack = NULL; static t_CKBOOL g_ct_go = FALSE; #endif // __CK_HID_CURSOR_TRACK__ #ifdef __CK_HID_WIIREMOTE__ // wii remote stuff static CFRunLoopSourceRef cfrlWiiRemoteSource = NULL; static void WiiRemote_cfrl_callback( void * info ); #endif t_CKINT OSX_Hid_Device::preconfigure( io_object_t ioHIDDeviceObject ) { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == CFRunLoopGetCurrent() || rlHid == NULL ); if( preconfiged ) return 0; switch( type ) { case CK_HID_DEV_JOYSTICK: strncpy( name, "Joystick", 256 ); buttons = 0; axes = 0; wheels = 0; hats = 0; break; case CK_HID_DEV_MOUSE: strncpy( name, "Mouse", 256 ); buttons = 0; axes = 0; wheels = 0; hats = -1; break; case CK_HID_DEV_KEYBOARD: strncpy( name, "Keyboard", 256 ); buttons = 0; axes = -1; wheels = -1; hats = -1; break; } // retrieve a dictionary of device properties kern_return_t kern_result = IORegistryEntryCreateCFProperties( ioHIDDeviceObject, &hidProperties, kCFAllocatorDefault, kNilOptions); if( kern_result != KERN_SUCCESS || hidProperties == NULL ) { hidProperties = NULL; return -1; } // get the device name, and copy it into the device record CFTypeRef refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( refCF ) CFStringGetCString( ( CFStringRef )refCF, name, 256, kCFStringEncodingASCII ); // retrieve uniquely identifying information if( !locationID ) { locationID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDLocationIDKey ) ); if( locationID ) CFRetain( locationID ); } if( !vendorID ) { vendorID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDVendorIDKey ) ); if( vendorID ) CFRetain( vendorID ); } if( !productID ) { productID = ( CFNumberRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductIDKey ) ); if( productID ) CFRetain( productID ); } if( !manufacturer ) { manufacturer = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( manufacturer ) CFRetain( manufacturer ); } if( !product ) { product = ( CFStringRef ) CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) ); if( product ) CFRetain( product ); } // create plugin interface IOReturn result; SInt32 score = 0; result = IOCreatePlugInInterfaceForService( ioHIDDeviceObject, kIOHIDDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; return -1; } #ifdef __LITTLE_ENDIAN__ /* MacBooks and MacBook Pros have some sort of "phantom" trackpad, which shows up in the HID registry and claims to no wheels. The device name is usually Trackpad with the manufacturer being Apple. This may disable legitimate Trackpads, but hopefully not... */ if( type == CK_HID_DEV_MOUSE && strncmp( "Trackpad", name, 256 ) == 0 ) { refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDManufacturerKey ) ); if( refCF != NULL && CFStringCompare( ( CFStringRef ) refCF, CFSTR( "Apple" ), 0 ) == 0 ) { preconfiged = TRUE; configure(); if( wheels == 0 ) // this is the "phantom" trackpad { // iterate through the element map, delete device element records map< IOHIDElementCookie, OSX_Hid_Device_Element * >::iterator iter, end; end = elements->end(); for( iter = elements->begin(); iter != end; iter++ ) delete iter->second; delete elements; elements = NULL; if( queue ) { ( *queue )->dispose( queue ); ( *queue )->Release( queue ); queue = NULL; } if( interface ) { ( *interface )->close( interface ); ( *interface )->Release( interface ); interface = NULL; } return -1; } } } #endif // __LITTLE_ENDIAN__ // register callback for removal notification, among a few other things result = IOServiceAddInterestNotification( newDeviceNotificationPort, ioHIDDeviceObject, kIOGeneralInterest, Hid_device_removed, this, &removal_notification ); preconfiged = TRUE; return 0; } t_CKINT OSX_Hid_Device::configure() { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == NULL || rlHid == CFRunLoopGetCurrent() ); if( configed ) return 0; if( !preconfiged ) return -1; EM_log( CK_LOG_INFO, "hid: configuring %s", name ); // create the device interface HRESULT plugInResult = S_OK; plugInResult = (*plugInInterface)->QueryInterface( plugInInterface, CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ), ( LPVOID * ) &interface ); (*plugInInterface)->Release( plugInInterface ); plugInInterface = NULL; if( plugInResult != S_OK ) { CFRelease( hidProperties ); hidProperties = NULL; return -1; } // open the interface IOReturn result; result = (*interface)->open( interface, 0 ); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; (*interface)->Release( interface ); interface = NULL; return -1; } // create an event queue, so we dont have to poll individual elements queue = (*interface)->allocQueue( interface ); if( !queue ) { CFRelease( hidProperties ); hidProperties = NULL; (*interface)->close( interface ); (*interface)->Release( interface ); interface = NULL; return -1; } result = (*queue)->create( queue, 0, event_queue_size ); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; (*queue)->Release( queue ); queue = NULL; (*interface)->close( interface ); (*interface)->Release( interface ); interface = NULL; return -1; } // set up the call back mechanism result = (*queue)->createAsyncEventSource( queue, &eventSource ); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; (*queue)->dispose( queue ); (*queue)->Release( queue ); queue = NULL; (*interface)->close( interface ); (*interface)->Release( interface ); interface = NULL; return -1; } result = (*queue)->setEventCallout( queue, Hid_callback, NULL, this ); if( result != kIOReturnSuccess ) { CFRelease( hidProperties ); hidProperties = NULL; (*queue)->dispose( queue ); (*queue)->Release( queue ); queue = NULL; (*interface)->close( interface ); (*interface)->Release( interface ); interface = NULL; return -1; } if( hidProperties != NULL ) { if( elements == NULL ) { // retrieve the array of elements... CFTypeRef refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDElementKey ) ); if( !refCF ) { CFRelease( hidProperties ); hidProperties = NULL; (*queue)->dispose( queue ); (*queue)->Release( queue ); queue = NULL; (*interface)->close( interface ); (*interface)->Release( interface ); interface = NULL; return -1; } // ...allocate space for element records... elements = new map< IOHIDElementCookie, OSX_Hid_Device_Element * >; // axes = 0; // buttons = 0; // hats = 0; // ...and parse the element array recursively enumerate_elements( ( CFArrayRef ) refCF ); } else { map< IOHIDElementCookie, OSX_Hid_Device_Element * >::iterator iter, end; end = elements->end(); for( iter = elements->begin(); iter != end; iter++ ) ( *queue )->addElement( queue, iter->second->cookie, 0 ); } CFRelease( hidProperties ); hidProperties = NULL; } configed = TRUE; return 0; } //------------------------------------------------------------------------------ // name: enumerate_device_elements // desc: perform depth depth first search on potentially nested arrays of // elements on the device, add found elements to the vector //------------------------------------------------------------------------------ void OSX_Hid_Device::enumerate_elements( CFArrayRef cfElements ) { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == NULL || rlHid == CFRunLoopGetCurrent() ); CFTypeRef refCF = 0; CFDictionaryRef element_dictionary; OSX_Hid_Device_Element * element; t_CKINT usage_page, usage, element_type; IOReturn result; CFIndex i, len = CFArrayGetCount( cfElements ); for( i = 0; i < len; i++ ) { // retrieve the dictionary of the ith element's data refCF = CFArrayGetValueAtIndex( cfElements, i ); element_dictionary = ( CFDictionaryRef ) refCF; // get element type refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementTypeKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element_type ) ) continue; // get element usage page refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementUsagePageKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &usage_page ) ) continue; // get element usage refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementUsageKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &usage ) ) continue; switch( element_type ) { case kIOHIDElementTypeInput_Misc: case kIOHIDElementTypeInput_Button: case kIOHIDElementTypeInput_Axis: case kIOHIDElementTypeInput_ScanCodes: // an input of some sort switch( usage_page ) { case kHIDPage_GenericDesktop: switch( usage ) { case kHIDUsage_GD_X: case kHIDUsage_GD_Y: case kHIDUsage_GD_Z: case kHIDUsage_GD_Rx: case kHIDUsage_GD_Ry: case kHIDUsage_GD_Rz: case kHIDUsage_GD_Slider: case kHIDUsage_GD_Dial: // this is an axis if( axes == -1 ) continue; element = new OSX_Hid_Device_Element; element->num = axes; if( this->type == CK_HID_DEV_JOYSTICK ) element->type = CK_HID_JOYSTICK_AXIS; else element->type = CK_HID_MOUSE_MOTION; element->usage = usage; element->usage_page = usage_page; refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementCookieKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->cookie ) ) { delete element; continue; } refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementMinKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->min ) ) { delete element; continue; } refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementMaxKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->max ) ) { delete element; continue; } result = (*queue)->addElement( queue, element->cookie, 0 ); if( result != kIOReturnSuccess ) { delete element; continue; } EM_log( CK_LOG_FINE, "adding axis %d", axes ); (*elements)[element->cookie] = element; axes++; break; case kHIDUsage_GD_Wheel: // this is an wheel if( wheels == -1 ) continue; element = new OSX_Hid_Device_Element; element->num = wheels; if( this->type == CK_HID_DEV_JOYSTICK ) element->type = CK_HID_JOYSTICK_AXIS; else element->type = CK_HID_MOUSE_WHEEL; element->usage = usage; element->usage_page = usage_page; refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementCookieKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->cookie ) ) { delete element; continue; } result = (*queue)->addElement( queue, element->cookie, 0 ); if( result != kIOReturnSuccess ) { delete element; continue; } EM_log( CK_LOG_FINE, "adding wheel %d", wheels ); (*elements)[element->cookie] = element; wheels++; break; case kHIDUsage_GD_Hatswitch: // this is a hat if( hats == -1 ) continue; element = new OSX_Hid_Device_Element; element->type = CK_HID_JOYSTICK_HAT; element->num = hats; element->usage = usage; element->usage_page = usage_page; refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementCookieKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->cookie ) ) { delete element; continue; } result = (*queue)->addElement( queue, element->cookie, 0 ); if( result != kIOReturnSuccess ) { delete element; continue; } EM_log( CK_LOG_FINE, "adding hat %d", hats ); (*elements)[element->cookie] = element; hats++; break; default: EM_log( CK_LOG_INFO, "unknown page: %i usage: %i\n", usage_page, usage ); } break; case kHIDPage_Button: case kHIDPage_KeyboardOrKeypad: // this is a button if( buttons == -1 ) continue; /* filter out error and reserved usages*/ if( usage_page == kHIDPage_KeyboardOrKeypad && !( usage >= kHIDUsage_KeyboardA && usage <= kHIDUsage_KeyboardRightGUI ) ) continue; element = new OSX_Hid_Device_Element; element->type = CK_HID_BUTTON_DOWN; element->num = buttons; element->usage = usage; element->usage_page = usage_page; refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementCookieKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->cookie ) ) { delete element; continue; } result = (*queue)->addElement( queue, element->cookie, 0 ); if( result != kIOReturnSuccess ) { delete element; continue; } EM_log( CK_LOG_FINE, "adding button %d", buttons ); (*elements)[element->cookie] = element; buttons++; break; default: EM_log( CK_LOG_FINER, "unknown page: %i usage: %i\n", usage_page, usage ); } break; case kIOHIDElementTypeCollection: refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementKey ) ); if( !refCF ) continue; enumerate_elements( ( CFArrayRef ) refCF ); break; case kIOHIDElementTypeOutput: switch( usage_page ) { case kHIDPage_LEDs: /* filter out error and reserved usages */ if( usage > kHIDUsage_LED_ExternalPowerConnected ) continue; element = new OSX_Hid_Device_Element; refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementCookieKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->cookie ) ) { delete element; continue; } refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementMinKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->min ) ) { delete element; continue; } refCF = CFDictionaryGetValue( element_dictionary, CFSTR( kIOHIDElementMaxKey ) ); if( !refCF || !CFNumberGetValue( ( CFNumberRef ) refCF, kCFNumberLongType, &element->max ) ) { delete element; continue; } if( outputs == NULL ) outputs = new map< unsigned int, vector< OSX_Hid_Device_Element * > * >; if( outputs->find( CK_HID_LED ) == outputs->end() ) ( *outputs )[CK_HID_LED] = new vector< OSX_Hid_Device_Element * >; element->type = CK_HID_LED; element->num = ( *outputs )[CK_HID_LED]->size(); element->usage = usage; element->usage_page = usage_page; EM_log( CK_LOG_FINE, "adding led %d", element->num ); ( *outputs )[CK_HID_LED]->push_back( element ); break; } break; } } } t_CKINT OSX_Hid_Device::start() { // can only be called in Hid thread assert( rlHid == CFRunLoopGetCurrent() ); EM_log( CK_LOG_INFO, "hid: starting %s", name ); EM_pushlog(); // configure if needed if( !configed ) { // lock the device so we can mutate it this->lock(); // configure if( configure() ) { // error during configuration! this->unlock(); EM_log( CK_LOG_SEVERE, "hid: error configuring %s", name ); EM_poplog(); return -1; } this->unlock(); } EM_log( CK_LOG_INFO, "hid: adding %s to run loop", name ); CFRunLoopAddSource( rlHid, eventSource, kCFRunLoopChuckHidMode ); IOReturn result = ( *queue )->start( queue ); if( result != kIOReturnSuccess ) { EM_log( CK_LOG_SEVERE, "hid: error starting event queue for %s", name ); EM_poplog(); return -1; } EM_poplog(); return 0; } t_CKINT OSX_Hid_Device::stop() { // can only be called in Hid thread assert( rlHid == CFRunLoopGetCurrent() ); if( queue ) { IOReturn result = ( *queue )->stop( queue ); if( result != kIOReturnSuccess ) EM_log( CK_LOG_INFO, "hid: error stopping event queue for %s", name ); } CFRunLoopRemoveSource( rlHid, eventSource, kCFRunLoopChuckHidMode ); return 0; } t_CKBOOL OSX_Hid_Device::is_connected() const { if( plugInInterface == NULL && interface == NULL ) return FALSE; return TRUE; } t_CKBOOL OSX_Hid_Device::is_same_as( io_object_t ioHIDDeviceObject ) const { CFMutableDictionaryRef hidProperties2 = NULL; t_CKBOOL result = FALSE; // retrieve a dictionary of device properties kern_return_t kern_result = IORegistryEntryCreateCFProperties( ioHIDDeviceObject, &hidProperties2, kCFAllocatorDefault, kNilOptions ); if( kern_result != KERN_SUCCESS || hidProperties2 == NULL ) { return FALSE; } // gewang: moved these decl's above goto's CFNumberRef locationID2 = 0; CFNumberRef vendorID2 = 0; CFNumberRef productID2 = 0; CFStringRef manufacturer2 = 0; CFStringRef product2 = 0; // if no "uniquely identifying" info is available, then assume its new if( !locationID && !vendorID && !productID && !manufacturer && !product ) goto end; locationID2 = ( CFNumberRef ) CFDictionaryGetValue( hidProperties2, CFSTR( kIOHIDLocationIDKey ) ); if( ( locationID && !locationID2 ) || ( !locationID && locationID2 ) ) goto end; // not the same if( locationID && locationID2 && CFNumberCompare( locationID, locationID2, NULL ) ) goto end; // not the same vendorID2 = ( CFNumberRef ) CFDictionaryGetValue( hidProperties2, CFSTR( kIOHIDVendorIDKey ) ); if( ( vendorID && !vendorID2 ) || ( !vendorID && vendorID2 ) ) goto end; // not the same if( vendorID && vendorID2 && CFNumberCompare( vendorID, vendorID2, NULL ) ) goto end; // not the same productID2 = ( CFNumberRef ) CFDictionaryGetValue( hidProperties2, CFSTR( kIOHIDProductIDKey ) ); if( ( productID && !productID2 ) || ( !productID && productID2 ) ) goto end; // not the same if( productID && productID2 && CFNumberCompare( productID, productID2, NULL ) ) goto end; // not the same manufacturer2 = ( CFStringRef ) CFDictionaryGetValue( hidProperties2, CFSTR( kIOHIDManufacturerKey ) ); if( ( manufacturer && !manufacturer2 ) || ( !manufacturer && manufacturer2 ) ) goto end; // not the same if( manufacturer && manufacturer2 && CFStringCompare( manufacturer, manufacturer2, 0 ) ) goto end; // not the same product2 = ( CFStringRef ) CFDictionaryGetValue( hidProperties2, CFSTR( kIOHIDProductKey ) ); if( ( product && !product2 ) || ( !product && product2 ) ) goto end; // not the same if( product && product2 && CFStringCompare( product, product2, 0 ) ) goto end; // not the same // if execution reaches this point, then they are the same result = TRUE; end: CFRelease( hidProperties2 ); return result; } //------------------------------------------------------------------------------ // name: disconnect() // desc: called when device is physically disconnected from the machine. // deallocates per-connection resources, but leaves stuff that should be the // same across connections (element list, name, other general properties, etc) //------------------------------------------------------------------------------ void OSX_Hid_Device::disconnect() { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == NULL || rlHid == CFRunLoopGetCurrent() ); if( plugInInterface ) { ( *plugInInterface )->Release( plugInInterface ); plugInInterface = NULL; } if( queue ) { if( refcount ) { ( *queue )->stop( queue ); if( rlHid ) CFRunLoopRemoveSource( rlHid, eventSource, kCFRunLoopChuckHidMode ); } ( *queue )->dispose( queue ); ( *queue )->Release( queue ); queue = NULL; } if( interface ) { ( *interface )->close( interface ); ( *interface )->Release( interface ); interface = NULL; } if( removal_notification ) { IOObjectRelease( removal_notification ); removal_notification = NULL; } configed = FALSE; preconfiged = FALSE; } //------------------------------------------------------------------------------ // name: cleanup() // desc: deallocates all resources associated with the device //------------------------------------------------------------------------------ void OSX_Hid_Device::cleanup() { // can only be called in Hid thread, or if the hid thread hasnt started assert( rlHid == NULL || rlHid == CFRunLoopGetCurrent() ); disconnect(); // delete all elements if( elements ) { this->lock(); // iterate through the axis map, delete device element records map< IOHIDElementCookie, OSX_Hid_Device_Element * >::iterator iter, end; end = elements->end(); for( iter = elements->begin(); iter != end; iter++ ) delete iter->second; delete elements; elements = NULL; // TODO: delete outputs also this->unlock(); } if( hidProperties ) { CFRelease( hidProperties ); hidProperties = NULL; } this->lock(); if( locationID ) { CFRelease( locationID ); locationID = NULL; } if( vendorID ) { CFRelease( vendorID ); vendorID = NULL; } if( productID ) { CFRelease( productID ); productID = NULL; } if( manufacturer ) { CFRelease( manufacturer ); manufacturer = NULL; } if( product ) { CFRelease( product ); product = NULL; } this->unlock(); } static void Hid_key_table_init() { memset( g_hid_key_table, 0, sizeof( g_hid_key_table ) ); // ASCII letters g_hid_key_table[kHIDUsage_KeyboardA] = 'A'; g_hid_key_table[kHIDUsage_KeyboardB] = 'B'; g_hid_key_table[kHIDUsage_KeyboardC] = 'C'; g_hid_key_table[kHIDUsage_KeyboardD] = 'D'; g_hid_key_table[kHIDUsage_KeyboardE] = 'E'; g_hid_key_table[kHIDUsage_KeyboardF] = 'F'; g_hid_key_table[kHIDUsage_KeyboardG] = 'G'; g_hid_key_table[kHIDUsage_KeyboardH] = 'H'; g_hid_key_table[kHIDUsage_KeyboardI] = 'I'; g_hid_key_table[kHIDUsage_KeyboardJ] = 'J'; g_hid_key_table[kHIDUsage_KeyboardK] = 'K'; g_hid_key_table[kHIDUsage_KeyboardL] = 'L'; g_hid_key_table[kHIDUsage_KeyboardM] = 'M'; g_hid_key_table[kHIDUsage_KeyboardN] = 'N'; g_hid_key_table[kHIDUsage_KeyboardO] = 'O'; g_hid_key_table[kHIDUsage_KeyboardP] = 'P'; g_hid_key_table[kHIDUsage_KeyboardQ] = 'Q'; g_hid_key_table[kHIDUsage_KeyboardR] = 'R'; g_hid_key_table[kHIDUsage_KeyboardS] = 'S'; g_hid_key_table[kHIDUsage_KeyboardT] = 'T'; g_hid_key_table[kHIDUsage_KeyboardU] = 'U'; g_hid_key_table[kHIDUsage_KeyboardV] = 'V'; g_hid_key_table[kHIDUsage_KeyboardW] = 'W'; g_hid_key_table[kHIDUsage_KeyboardX] = 'X'; g_hid_key_table[kHIDUsage_KeyboardY] = 'Y'; g_hid_key_table[kHIDUsage_KeyboardZ] = 'Z'; // ASCII numbers g_hid_key_table[kHIDUsage_Keyboard1] = '1'; g_hid_key_table[kHIDUsage_Keyboard2] = '2'; g_hid_key_table[kHIDUsage_Keyboard3] = '3'; g_hid_key_table[kHIDUsage_Keyboard4] = '4'; g_hid_key_table[kHIDUsage_Keyboard5] = '5'; g_hid_key_table[kHIDUsage_Keyboard6] = '6'; g_hid_key_table[kHIDUsage_Keyboard7] = '7'; g_hid_key_table[kHIDUsage_Keyboard8] = '8'; g_hid_key_table[kHIDUsage_Keyboard9] = '9'; g_hid_key_table[kHIDUsage_Keyboard0] = '0'; // ASCII whitespace/control characters g_hid_key_table[kHIDUsage_KeyboardEscape] = '\e'; g_hid_key_table[kHIDUsage_KeyboardDeleteOrBackspace] = '\b'; g_hid_key_table[kHIDUsage_KeyboardReturnOrEnter] = '\n'; g_hid_key_table[kHIDUsage_KeyboardTab] = '\t'; g_hid_key_table[kHIDUsage_KeyboardSpacebar] = ' '; // ASCII symbols g_hid_key_table[kHIDUsage_KeyboardHyphen] = '-'; g_hid_key_table[kHIDUsage_KeyboardEqualSign] = '='; g_hid_key_table[kHIDUsage_KeyboardOpenBracket] = '['; g_hid_key_table[kHIDUsage_KeyboardCloseBracket] = ']'; g_hid_key_table[kHIDUsage_KeyboardBackslash] = '\\'; g_hid_key_table[kHIDUsage_KeyboardNonUSPound] = '#'; g_hid_key_table[kHIDUsage_KeyboardSemicolon] = ';'; g_hid_key_table[kHIDUsage_KeyboardQuote] = '\''; g_hid_key_table[kHIDUsage_KeyboardGraveAccentAndTilde] = '`'; g_hid_key_table[kHIDUsage_KeyboardComma] = ','; g_hid_key_table[kHIDUsage_KeyboardPeriod] = '.'; g_hid_key_table[kHIDUsage_KeyboardSlash] = '/'; // ASCII keypad symbols/whitespace g_hid_key_table[kHIDUsage_KeypadSlash] = '/'; g_hid_key_table[kHIDUsage_KeypadAsterisk] = '*'; g_hid_key_table[kHIDUsage_KeypadHyphen] = '-'; g_hid_key_table[kHIDUsage_KeypadPlus] = '+'; g_hid_key_table[kHIDUsage_KeypadEnter] = '\n'; // ASCII keypad numbers g_hid_key_table[kHIDUsage_Keypad1] = '1'; g_hid_key_table[kHIDUsage_Keypad2] = '2'; g_hid_key_table[kHIDUsage_Keypad3] = '3'; g_hid_key_table[kHIDUsage_Keypad4] = '4'; g_hid_key_table[kHIDUsage_Keypad5] = '5'; g_hid_key_table[kHIDUsage_Keypad6] = '6'; g_hid_key_table[kHIDUsage_Keypad7] = '7'; g_hid_key_table[kHIDUsage_Keypad8] = '8'; g_hid_key_table[kHIDUsage_Keypad9] = '9'; g_hid_key_table[kHIDUsage_Keypad0] = '0'; // ASCII keypad symbols g_hid_key_table[kHIDUsage_KeypadPeriod] = '.'; g_hid_key_table[kHIDUsage_KeyboardNonUSBackslash] = '\\'; g_hid_key_table[kHIDUsage_KeypadEqualSign] = '='; g_hid_key_table[kHIDUsage_KeypadComma] = ','; g_hid_key_table[kHIDUsage_KeypadEqualSignAS400] = '='; } t_CKINT Hid_hwkey_to_ascii( t_CKINT hwkey ) { if( hwkey < 0 || hwkey >= sizeof( g_hid_key_table ) ) return -1; return g_hid_key_table[hwkey]; } void Hid_init() { Hid_key_table_init(); rlHid = CFRunLoopGetCurrent(); // set up notification for new added devices/removed devices CFRunLoopAddSource( rlHid, IONotificationPortGetRunLoopSource( newDeviceNotificationPort ), kCFRunLoopChuckHidMode ); // add open/close operation source CFRunLoopSourceContext opSourceContext; opSourceContext.version = 0; opSourceContext.info = NULL; opSourceContext.retain = NULL; opSourceContext.release = NULL; opSourceContext.copyDescription = NULL; opSourceContext.equal = NULL; opSourceContext.hash = NULL; opSourceContext.schedule = NULL; opSourceContext.cancel = NULL; opSourceContext.perform = Hid_do_operation; CFRunLoopSourceRef _hidOpSource = CFRunLoopSourceCreate( kCFAllocatorDefault, 0, &opSourceContext ); CFRunLoopAddSource( rlHid, _hidOpSource, kCFRunLoopChuckHidMode ); hidOpSource = _hidOpSource; Hid_do_operation( NULL ); #ifdef __CK_HID_WIIREMOTE__ // add wii remote source CFRunLoopSourceContext wrSourceContext; wrSourceContext.version = 0; wrSourceContext.info = NULL; wrSourceContext.retain = NULL; wrSourceContext.release = NULL; wrSourceContext.copyDescription = NULL; wrSourceContext.equal = NULL; wrSourceContext.hash = NULL; wrSourceContext.schedule = NULL; wrSourceContext.cancel = NULL; wrSourceContext.perform = WiiRemote_cfrl_callback; CFRunLoopSourceRef _cfrlWiiRemoteSource = CFRunLoopSourceCreate( kCFAllocatorDefault, 0, &wrSourceContext ); CFRunLoopAddSource( rlHid, _cfrlWiiRemoteSource, kCFRunLoopChuckHidMode ); cfrlWiiRemoteSource = _cfrlWiiRemoteSource; WiiRemote_cfrl_callback( NULL ); #endif } void Hid_init2() { // verify that the joystick system has not already been initialized if( g_hid_init == TRUE ) return; g_hid_init = TRUE; IOReturn result = kIOReturnSuccess; io_iterator_t hidObjectIterator = 0; CFTypeRef refCF; t_CKINT filter_usage_page = kHIDPage_GenericDesktop; // allocate vectors of device records joysticks = new xvector< OSX_Hid_Device * >; mice = new xvector< OSX_Hid_Device * >; keyboards = new xvector< OSX_Hid_Device * >; joystick_names = new xmultimap< string, OSX_Hid_Device * >; mouse_names = new xmultimap< string, OSX_Hid_Device * >; keyboard_names = new xmultimap< string, OSX_Hid_Device * >; hid_operation_buffer = new CBufferSimple; hid_operation_buffer->initialize( 20, sizeof( OSX_Hid_op ) ); CFMutableDictionaryRef hidMatchDictionary = IOServiceMatching( kIOHIDDeviceKey ); if( !hidMatchDictionary ) { EM_log( CK_LOG_SEVERE, "hid: error: unable to retrieving hidMatchDictionary, unable to initialize" ); return; } refCF = ( CFTypeRef ) CFNumberCreate( kCFAllocatorDefault, kCFNumberLongType, &filter_usage_page ); CFDictionarySetValue( hidMatchDictionary, CFSTR( kIOHIDPrimaryUsagePageKey ), refCF ); newDeviceNotificationPort = IONotificationPortCreate( kIOMasterPortDefault ); result = IOServiceAddMatchingNotification( newDeviceNotificationPort, kIOFirstMatchNotification, hidMatchDictionary, Hid_new_devices, NULL, &hidObjectIterator ); if( result != kIOReturnSuccess || hidObjectIterator == 0 ) { EM_log( CK_LOG_SEVERE, "hid: error: unable to retrieving matching services, unable to initialize" ); return; } CFRelease( refCF ); Hid_new_devices( NULL, hidObjectIterator ); } static void Hid_new_devices( void * refcon, io_iterator_t iterator ) { EM_log( CK_LOG_INFO, "hid: new device(s) found" ); char __temp[256]; CFTypeRef refCF = NULL; io_object_t ioHIDDeviceObject = 0; t_CKINT usage, usage_page; t_CKINT joysticks_seen = joysticks->size(), mice_seen = mice->size(), keyboards_seen = keyboards->size(); while( ioHIDDeviceObject = IOIteratorNext( iterator ) ) { // ascertain device information // first, determine the device usage page and usage usage = usage_page = -1; refCF = IORegistryEntryCreateCFProperty( ioHIDDeviceObject, CFSTR( kIOHIDPrimaryUsagePageKey ), kCFAllocatorDefault, kNilOptions ); if( !refCF ) continue; CFNumberGetValue( ( CFNumberRef )refCF, kCFNumberLongType, &usage_page ); CFRelease( refCF ); refCF = IORegistryEntryCreateCFProperty( ioHIDDeviceObject, CFSTR( kIOHIDPrimaryUsageKey ), kCFAllocatorDefault, kNilOptions); if( !refCF ) continue; CFNumberGetValue( ( CFNumberRef )refCF, kCFNumberLongType, &usage ); CFRelease( refCF ); if ( usage_page == kHIDPage_GenericDesktop ) { if( usage == kHIDUsage_GD_Joystick || usage == kHIDUsage_GD_GamePad ) // this is a joystick, create a new item in the joystick array { // see if this an device that was disconnected being reconnected refCF = IORegistryEntryCreateCFProperty( ioHIDDeviceObject, CFSTR( kIOHIDProductKey ), kCFAllocatorDefault, kNilOptions); if( refCF ) { CFStringGetCString( ( CFStringRef ) refCF, __temp, 256, kCFStringEncodingASCII ); CFRelease( refCF ); } else strncpy( __temp, "Joystick", 256 ); pair< xmultimap< string, OSX_Hid_Device * >::const_iterator, xmultimap< string, OSX_Hid_Device * >::const_iterator > name_range = joystick_names->equal_range( string( __temp ) ); xmultimap< string, OSX_Hid_Device * >::const_iterator start = name_range.first, end = name_range.second; t_CKBOOL match_found = FALSE; for( ; start != end; start++ ) { OSX_Hid_Device * old_device = ( *start ).second; if( !old_device->is_connected() && old_device->is_same_as( ioHIDDeviceObject ) ) { match_found = TRUE; EM_log( CK_LOG_INFO, "hid: joystick %s reattached", old_device->name ); if( old_device->preconfigure( ioHIDDeviceObject ) ) { EM_log( CK_LOG_INFO, "hid: error during reconfiguration of %s", old_device->name ); break; } if( old_device->refcount && !old_device->start() ) { HidMsg msg; msg.device_type = old_device->type; msg.device_num = old_device->num; msg.type = CK_HID_DEVICE_CONNECTED; HidInManager::push_message( msg ); } break; } } if( match_found ) continue; // create a new device record for the device EM_log( CK_LOG_INFO, "hid: preconfiguring joystick %i", joysticks_seen ); EM_pushlog(); // allocate the device record, set usage page and usage OSX_Hid_Device * new_device = new OSX_Hid_Device; new_device->type = CK_HID_DEV_JOYSTICK; new_device->num = joysticks->size(); new_device->usage_page = usage_page; new_device->usage = usage; if( !new_device->preconfigure( ioHIDDeviceObject ) ) { joysticks->lock(); joysticks->push_back( new_device ); joysticks->unlock(); joystick_names->lock(); joystick_names->insert( pair< string, OSX_Hid_Device * >( string( new_device->name ), new_device ) ); joystick_names->unlock(); } else { EM_log( CK_LOG_INFO, "hid: error during preconfiguration of joystick %i", joysticks_seen ); delete new_device; } joysticks_seen++; EM_poplog(); } if( usage == kHIDUsage_GD_Mouse ) // this is a mouse { // see if this an device that was disconnected being reconnected refCF = IORegistryEntryCreateCFProperty( ioHIDDeviceObject, CFSTR( kIOHIDProductKey ), kCFAllocatorDefault, kNilOptions); if( refCF ) { CFStringGetCString( ( CFStringRef ) refCF, __temp, 256, kCFStringEncodingASCII ); CFRelease( refCF ); } else strncpy( __temp, "Mouse", 256 ); pair< xmultimap< string, OSX_Hid_Device * >::const_iterator, xmultimap< string, OSX_Hid_Device * >::const_iterator > name_range = mouse_names->equal_range( string( __temp ) ); xmultimap< string, OSX_Hid_Device * >::const_iterator start = name_range.first, end = name_range.second; t_CKBOOL match_found = FALSE; for( ; start != end; start++ ) { OSX_Hid_Device * old_device = ( *start ).second; if( !old_device->is_connected() && old_device->is_same_as( ioHIDDeviceObject ) ) { match_found = TRUE; EM_log( CK_LOG_INFO, "hid: mouse %s reattached", old_device->name ); if( old_device->preconfigure( ioHIDDeviceObject ) ) { EM_log( CK_LOG_INFO, "hid: error during reconfiguration of %s", old_device->name ); break; } if( old_device->refcount && !old_device->start() ) { HidMsg msg; msg.device_type = old_device->type; msg.device_num = old_device->num; msg.type = CK_HID_DEVICE_CONNECTED; HidInManager::push_message( msg ); } break; } } if( match_found ) continue; // create a new device record for the device EM_log( CK_LOG_INFO, "hid: preconfiguring mouse %i", mice_seen ); EM_pushlog(); // allocate the device record, set usage page and usage OSX_Hid_Device * new_device = new OSX_Hid_Device; new_device->type = CK_HID_DEV_MOUSE; new_device->num = mice->size(); new_device->usage_page = usage_page; new_device->usage = usage; if( !new_device->preconfigure( ioHIDDeviceObject ) ) { mice->lock(); mice->push_back( new_device ); mice->unlock(); mouse_names->lock(); mouse_names->insert( pair< string, OSX_Hid_Device * >( string( new_device->name ), new_device ) ); mouse_names->unlock(); } else { EM_log( CK_LOG_INFO, "hid: error during preconfiguration of mouse %i", mice_seen ); delete new_device; } mice_seen++; EM_poplog(); } if( usage == kHIDUsage_GD_Keyboard || usage == kHIDUsage_GD_Keypad ) // this is a keyboard { // see if this an device that was disconnected being reconnected refCF = IORegistryEntryCreateCFProperty( ioHIDDeviceObject, CFSTR( kIOHIDProductKey ), kCFAllocatorDefault, kNilOptions); if( refCF ) { CFStringGetCString( ( CFStringRef ) refCF, __temp, 256, kCFStringEncodingASCII ); CFRelease( refCF ); } else strncpy( __temp, "Keyboard", 256 ); pair< xmultimap< string, OSX_Hid_Device * >::const_iterator, xmultimap< string, OSX_Hid_Device * >::const_iterator > name_range = keyboard_names->equal_range( string( __temp ) ); xmultimap< string, OSX_Hid_Device * >::const_iterator start = name_range.first, end = name_range.second; t_CKBOOL match_found = FALSE; for( ; start != end; start++ ) { OSX_Hid_Device * old_device = ( *start ).second; if( !old_device->is_connected() && old_device->is_same_as( ioHIDDeviceObject ) ) { match_found = TRUE; EM_log( CK_LOG_INFO, "hid: keyboard %s reattached", old_device->name ); if( old_device->preconfigure( ioHIDDeviceObject ) ) { EM_log( CK_LOG_INFO, "hid: error during reconfiguration of %s", old_device->name ); break; } if( old_device->refcount && !old_device->start() ) { HidMsg msg; msg.device_type = old_device->type; msg.device_num = old_device->num; msg.type = CK_HID_DEVICE_CONNECTED; HidInManager::push_message( msg ); } break; } } if( match_found ) continue; // create a new device record for the device EM_log( CK_LOG_INFO, "hid: preconfiguring keyboard %i", keyboards_seen ); EM_pushlog(); // allocate the device record, set usage page and usage OSX_Hid_Device * new_device = new OSX_Hid_Device; new_device->type = CK_HID_DEV_KEYBOARD; new_device->num = keyboards->size(); new_device->usage_page = usage_page; new_device->usage = usage; if( !new_device->preconfigure( ioHIDDeviceObject ) ) { keyboards->lock(); keyboards->push_back( new_device ); keyboards->unlock(); keyboard_names->lock(); keyboard_names->insert( pair< string, OSX_Hid_Device * >( string( new_device->name ), new_device ) ); keyboard_names->unlock(); } else { EM_log( CK_LOG_INFO, "hid: error during preconfiguration of keyboard %i", keyboards_seen ); delete new_device; } keyboards_seen++; EM_poplog(); } } } } void Hid_device_removed( void * refcon, io_service_t service, natural_t messageType, void * messageArgument ) { if( messageType == kIOMessageServiceIsTerminated && refcon ) { OSX_Hid_Device * device = ( OSX_Hid_Device * ) refcon; if( device->is_connected() ) { EM_log( CK_LOG_INFO, "hid: %s disconnected", device->name ); device->lock(); device->disconnect(); device->unlock(); HidMsg msg; msg.device_type = device->type; msg.device_num = device->num; msg.type = CK_HID_DEVICE_DISCONNECTED; HidInManager::push_message( msg ); } } } void Hid_poll() { CFRunLoopRunInMode( kCFRunLoopChuckHidMode, 60 * 60 * 24, false ); } void Hid_callback( void * target, IOReturn result, void * refcon, void * sender) { OSX_Hid_Device * device = ( OSX_Hid_Device * ) refcon; OSX_Hid_Device_Element * element; AbsoluteTime atZero = { 0, 0 }; IOHIDEventStruct event; HidMsg msg; while( result == kIOReturnSuccess ) { result = ( *( device->queue ) )->getNextEvent( device->queue, &event, atZero, 0 ); if( result == kIOReturnUnderrun ) break; if( result != kIOReturnSuccess ) { EM_log( CK_LOG_INFO, "hid: warning: getNextEvent failed" ); break; } element = ( *( device->elements ) )[event.elementCookie]; msg.clear(); msg.device_type = device->type; msg.device_num = device->num; msg.type = element->type; msg.eid = element->num; switch( msg.type ) { case CK_HID_JOYSTICK_AXIS: // scale the value to [-1.0, 1.0] msg.fdata[0] = ((t_CKFLOAT)(event.value - element->min)) * 2.0 / ((t_CKFLOAT)(element->max - element->min)) - 1.0; break; case CK_HID_JOYSTICK_HAT: msg.idata[0] = event.value; break; case CK_HID_MOUSE_MOTION: { // gewang: added msg.eid = 0; if( element->usage == kHIDUsage_GD_X ) { msg.idata[0] = event.value; msg.idata[1] = 0; } else { msg.idata[0] = 0; msg.idata[1] = event.value; } #ifndef __CK_HID_CURSOR_TRACK__ Point p; GetGlobalMouse( &p ); msg.idata[2] = p.h; msg.idata[3] = p.v; CGDirectDisplayID display; CGDisplayCount displayCount; CGPoint cgp; cgp.x = p.h; cgp.y = p.v; if( CGGetDisplaysWithPoint( cgp, 1, &display, &displayCount ) == kCGErrorSuccess ) { CGRect bounds = CGDisplayBounds( display ); msg.fdata[0] = ( ( t_CKFLOAT ) ( p.h - bounds.origin.x ) ) / ( bounds.size.width - 1 ); msg.fdata[1] = ( ( t_CKFLOAT ) ( p.v - bounds.origin.y ) ) / ( bounds.size.height - 1 ); } #else msg.idata[2] = cursorX; msg.idata[3] = cursorY; msg.fdata[0] = scaledCursorX; msg.fdata[1] = scaledCursorY; #endif // __CK_HID_CURSOR_TRACK__ } // gewang: added break; case CK_HID_MOUSE_WHEEL: msg.eid = 0; if( element->num == 1 ) // "X" wheel motion { msg.idata[0] = event.value; msg.idata[1] = 0; } else // "Y" wheel motion - the default for single wheel systems { msg.idata[0] = 0; msg.idata[1] = event.value; } break; case CK_HID_BUTTON_DOWN: if( event.value == 0 ) msg.type = CK_HID_BUTTON_UP; msg.idata[0] = event.value; if( msg.device_type == CK_HID_DEV_KEYBOARD ) { msg.eid = element->usage; msg.idata[1] = element->usage; msg.idata[2] = Hid_hwkey_to_ascii( element->usage ); } break; } HidInManager::push_message( msg ); } } static void Hid_do_operation( void * info ) { OSX_Hid_op op; while( hid_operation_buffer->get( &op, 1 ) ) { OSX_Hid_Device * device = NULL; switch( op.type ) { case OSX_Hid_op::open: if( op.index >= op.v->size() ) { EM_log( CK_LOG_SEVERE, "hid: error: no such device %i", op.index ); return; } device = op.v->at( op.index ); if( device->refcount == 0 ) device->start(); device->refcount++; break; case OSX_Hid_op::close: if( op.index >= op.v->size() ) { EM_log( CK_LOG_SEVERE, "hid: error: no such device %i", op.index ); return; } device = op.v->at( op.index ); device->refcount--; if( device->refcount == 0 ) device->stop(); break; } } } void Hid_quit() { // stop the run loop; since thread_going is FALSE, the poll thread will exit if( rlHid ) CFRunLoopStop( rlHid ); if( hidOpSource ) { CFRunLoopRemoveSource( rlHid, hidOpSource, kCFRunLoopChuckHidMode ); CFRelease( hidOpSource ); hidOpSource = NULL; } if( newDeviceNotificationPort ) { IONotificationPortDestroy( newDeviceNotificationPort ); newDeviceNotificationPort = NULL; } rlHid = NULL; #ifdef __CK_HID_CURSOR_TRACK__ Mouse_stop_cursor_track(); #endif // __CK_HID_CURSOR_TRACK__ } void Hid_quit2() { if( g_hid_init == FALSE ) return; g_hid_init = FALSE; delete hid_operation_buffer; xvector< OSX_Hid_Device * >::size_type i, len; len = joysticks->size(); for( i = 0; i < len; i++ ) delete joysticks->at( i ); delete joysticks; joysticks = NULL; len = mice->size(); for( i = 0; i < len; i++ ) delete mice->at( i ); delete mice; mice = NULL; len = keyboards->size(); for( i = 0; i < len; i++ ) delete keyboards->at( i ); delete keyboards; keyboards = NULL; // TODO: delete xmultimaps } int Hid_count( xvector< OSX_Hid_Device * > * v ) { if( v == NULL ) return 0; v->lock(); int count = v->size(); v->unlock(); return count; } int Hid_open( xvector< OSX_Hid_Device * > * v, int i ) { if( v == NULL || i < 0 ) return -1; v->lock(); if( i >= v->size() ) { v->unlock(); return -1; } v->unlock(); OSX_Hid_op op; op.type = OSX_Hid_op::open; op.v = v; op.index = i; hid_operation_buffer->put( &op, 1 ); if( hidOpSource && rlHid ) { CFRunLoopSourceSignal( hidOpSource ); CFRunLoopWakeUp( rlHid ); } return 0; } int Hid_close( xvector< OSX_Hid_Device * > * v, int i ) { if( v == NULL || i < 0 ) return -1; v->lock(); if( i >= v->size() ) { v->unlock(); return -1; } v->unlock(); OSX_Hid_op op; op.type = OSX_Hid_op::close; op.v = v; op.index = i; hid_operation_buffer->put( &op, 1 ); if( hidOpSource && rlHid ) { CFRunLoopSourceSignal( hidOpSource ); CFRunLoopWakeUp( rlHid ); } return 0; } const char * Hid_name( xvector< OSX_Hid_Device * > * v, int i ) { if( v == NULL || i < 0 ) return NULL; v->lock(); if( i >= v->size() ) { v->unlock(); return NULL; } OSX_Hid_Device * device = v->at( i ); v->unlock(); device->lock(); const char * name = device->name; device->unlock(); return name; } #pragma mark OS X Joystick support void Joystick_init() { Hid_init2(); } void Joystick_poll() { } void Joystick_quit() { Hid_quit2(); } int Joystick_count() { return Hid_count( joysticks ); } int Joystick_open( int js ) { return Hid_open( joysticks, js ); } int Joystick_close( int js ) { return Hid_close( joysticks, js ); } const char * Joystick_name( int js ) { return Hid_name( joysticks, js ); } #pragma mark OS X Mouse support void Mouse_init() { Hid_init2(); } void Mouse_poll() { } void Mouse_quit() { Hid_quit2(); } int Mouse_count() { return Hid_count( mice ); } int Mouse_open( int m ) { return Hid_open( mice, m ); } int Mouse_close( int m ) { return Hid_close( mice, m ); } const char * Mouse_name( int m ) { return Hid_name( mice, m ); } #ifdef __CK_HID_CURSOR_TRACK__ CGPoint CGEventGetLocation(CGEventRef event); CGEventRef Mouse_cursor_track_cb( CGEventTapProxy proxy, CGEventType type, CGEventRef event, void * refcon ) { CGPoint p = CGEventGetLocation( event ); cursorX = ( t_CKINT ) p.x; cursorY = ( t_CKINT ) p.y; CGDirectDisplayID display; CGDisplayCount displayCount; if( CGGetDisplaysWithPoint( p, 1, &display, &displayCount ) == kCGErrorSuccess ) { CGRect bounds = CGDisplayBounds( display ); scaledCursorX = ( ( t_CKFLOAT ) ( p.x - bounds.origin.x ) ) / ( bounds.size.width - 1 ); scaledCursorY = ( ( t_CKFLOAT ) ( p.y - bounds.origin.y ) ) / ( bounds.size.height - 1 ); } return event; } void * Mouse_cursor_track( void * ) { EM_log( CK_LOG_INFO, "hid: starting cursor track" ); cursorX = 0; cursorY = 0; rlCursorTrack = CFRunLoopGetCurrent(); CFMachPortRef machPort = CGEventTapCreate( kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, CGEventMaskBit( kCGEventMouseMoved ), Mouse_cursor_track_cb, NULL ); CFRunLoopSourceRef tapSource; if( machPort != NULL ) { tapSource = CFMachPortCreateRunLoopSource( NULL, machPort, 0 ); CFRunLoopAddSource( rlCursorTrack, tapSource, kCFRunLoopChuckHidMode ); } else { EM_log( CK_LOG_WARNING, "hid: cursor position listener startup failed" ); return 0; } while( g_ct_go ) CFRunLoopRunInMode( kCFRunLoopChuckHidMode, 60 * 60 * 24, FALSE ); CFRelease( machPort ); CFRelease( tapSource ); rlCursorTrack = NULL; EM_log( CK_LOG_INFO, "hid: stopping cursor track" ); return 0; } #endif // __CK_HID_CURSOR_TRACK__ int Mouse_start_cursor_track() { #ifdef __CK_HID_CURSOR_TRACK__ if( &CGEventTapCreate == NULL ) return -1; if( g_ct_go ) return 0; g_ct_go = TRUE; pthread_t ct_thread; if( pthread_create( &ct_thread, NULL, Mouse_cursor_track, NULL ) != 0 ) { EM_log( CK_LOG_WARNING, "hid: cursor track thread failed to start" ); return -1; } return 0; #else return -1; #endif // __CK_HID_CURSOR_TRACK__ } int Mouse_stop_cursor_track() { #ifdef __CK_HID_CURSOR_TRACK__ if( g_ct_go ) { g_ct_go = FALSE; if( rlCursorTrack ) CFRunLoopStop( rlCursorTrack ); cursorX = 0; cursorY = 0; } #endif // __CK_HID_CURSOR_TRACK__ return 0; } //#endif /* __CK_HID_CURSORTRACK__ */ #pragma mark OS X Keyboard support void Keyboard_init() { Hid_init2(); } void Keyboard_poll() { } void Keyboard_quit() { Hid_quit2(); } int Keyboard_count() { return Hid_count( keyboards ); } int Keyboard_open( int k ) { return Hid_open( keyboards, k ); } int Keyboard_close( int k ) { return Hid_close( keyboards, k ); } int Keyboard_send( int k, const HidMsg * msg ) { if( keyboards == NULL || k < 0 || k >= keyboards->size() ) return -1; OSX_Hid_Device * keyboard = ( *keyboards )[k]; if( keyboard->outputs == NULL || // no outputs keyboard->outputs->find( msg->type ) == keyboard->outputs->end() ) // no outputs of that type return -1; if( msg->eid < 0 || msg->eid >= ( *( keyboard->outputs ) )[msg->type]->size() ) // invalid output type element number return -1; OSX_Hid_Device_Element * output = ( *( *( keyboard->outputs ) )[msg->type] )[msg->eid]; IOHIDEventStruct eventStruct; eventStruct.type = kIOHIDElementTypeOutput; eventStruct.elementCookie = output->cookie; eventStruct.timestamp = UpTime(); eventStruct.longValueSize = 0; eventStruct.longValue = NULL; if( msg->idata[0] < output->min ) eventStruct.value = output->min; else if( msg->idata[0] > output->max ) eventStruct.value = output->max; else eventStruct.value = msg->idata[0]; IOReturn result; result = ( *( keyboard->interface ) )->setElementValue( keyboard->interface, output->cookie, &eventStruct, 0, 0, 0, 0 ); if( result != kIOReturnSuccess ) return -1; return 0; } const char * Keyboard_name( int k ) { return Hid_name( keyboards, k ); } #pragma mark OS X Tilt/Sudden Motion Sensor support enum { kSMSPowerbookDataType, kSMSMacBookProDataType }; static struct t_TiltSensor_data { union { struct t_powerbook { int8_t x; int8_t y; int8_t z; int8_t pad[57]; } powerbook; struct t_macbookpro { int16_t x; int16_t y; int16_t z; int8_t pad[34]; } macbookpro; } data; int kernFunc; char * servMatch; int dataType; io_connect_t dataPort; int detected; // 0 = detection not yet run, -1 = no sensor found, 1 = sensor found int refcount; t_TiltSensor_data() { refcount = 0; kernFunc = 0; servMatch = NULL; dataType = -1; dataPort = 0; detected = 0; } } TiltSensor_data; static int TiltSensor_test( int kernFunc, char * servMatch, int dataType ) { kern_return_t result; io_iterator_t iterator; io_object_t aDevice; io_connect_t dataPort; IOItemCount structureInputSize; IOByteCount structureOutputSize; CFMutableDictionaryRef matchingDictionary = IOServiceMatching( servMatch ); result = IOServiceGetMatchingServices( kIOMasterPortDefault, matchingDictionary, &iterator ); if( result != KERN_SUCCESS ) return 0; aDevice = IOIteratorNext( iterator ); IOObjectRelease( iterator ); if( aDevice == 0 ) return 0; result = IOServiceOpen( aDevice, mach_task_self(), 0, &dataPort ); IOObjectRelease( aDevice ); if ( result != KERN_SUCCESS ) return 0; switch( dataType ) { case kSMSPowerbookDataType: structureInputSize = sizeof( TiltSensor_data.data.powerbook ); structureOutputSize = sizeof( TiltSensor_data.data.powerbook ); break; case kSMSMacBookProDataType: structureInputSize = sizeof( TiltSensor_data.data.macbookpro ); structureOutputSize = sizeof( TiltSensor_data.data.macbookpro ); break; default: IOServiceClose( dataPort ); return 0; } memset( &TiltSensor_data.data, 0, sizeof( TiltSensor_data.data ) ); memset( &TiltSensor_data.data, 0, sizeof( TiltSensor_data.data ) ); result = IOConnectMethodStructureIStructureO( dataPort, kernFunc, structureInputSize, &structureOutputSize, &TiltSensor_data.data, &TiltSensor_data.data ); if ( result != KERN_SUCCESS ) { IOServiceClose( dataPort ); return 0; } // leave dataPort open for future use TiltSensor_data.dataPort = dataPort; return 1; } static int TiltSensor_do_read() { kern_return_t result; IOItemCount structureInputSize; IOByteCount structureOutputSize; switch( TiltSensor_data.dataType ) { case kSMSPowerbookDataType: structureInputSize = sizeof( TiltSensor_data.data.powerbook ); structureOutputSize = sizeof( TiltSensor_data.data.powerbook ); break; case kSMSMacBookProDataType: structureInputSize = sizeof( TiltSensor_data.data.macbookpro ); structureOutputSize = sizeof( TiltSensor_data.data.macbookpro ); break; default: return 0; } memset( &TiltSensor_data.data, 0, sizeof( TiltSensor_data.data ) ); memset( &TiltSensor_data.data, 0, sizeof( TiltSensor_data.data ) ); result = IOConnectMethodStructureIStructureO( TiltSensor_data.dataPort, TiltSensor_data.kernFunc, structureInputSize, &structureOutputSize, &TiltSensor_data.data, &TiltSensor_data.data ); return 1; } static int TiltSensor_detect() { // try different interfaces until we find one that works SInt32 osx_version; int powerbookKernFunc = 0; Gestalt( gestaltSystemVersion, &osx_version ); if( osx_version == 0x1040 || osx_version == 0x1041 || osx_version == 0x1042 || osx_version == 0x1043 ) powerbookKernFunc = 24; else powerbookKernFunc = 21; // ibook/powerbook (OS X 10.4.x) tilt sensor interface if( TiltSensor_test( powerbookKernFunc, "IOI2CMotionSensor", kSMSPowerbookDataType ) ) { TiltSensor_data.kernFunc = powerbookKernFunc; TiltSensor_data.dataType = kSMSPowerbookDataType; TiltSensor_data.detected = 1; return 1; } // hi resolution powerbook tilt sensor interface if( TiltSensor_test( powerbookKernFunc, "PMUMotionSensor", kSMSPowerbookDataType ) ) { TiltSensor_data.kernFunc = powerbookKernFunc; TiltSensor_data.dataType = kSMSPowerbookDataType; TiltSensor_data.detected = 1; return 1; } // mac book (pro) tilt sensor interface if( TiltSensor_test( 5, "SMCMotionSensor", kSMSMacBookProDataType ) ) { TiltSensor_data.kernFunc = 5; TiltSensor_data.dataType = kSMSMacBookProDataType; TiltSensor_data.detected = 1; return 1; } TiltSensor_data.detected = -1; return 0; } void TiltSensor_init() { } void TiltSensor_quit() { if( TiltSensor_data.dataPort == 0 ) IOServiceClose( TiltSensor_data.dataPort ); } void TiltSensor_probe() { } int TiltSensor_count() { if( TiltSensor_data.detected == 0 ) TiltSensor_detect(); if( TiltSensor_data.detected == -1 ) return 0; else if( TiltSensor_data.detected == 1 ) return 1; return 0; } int TiltSensor_open( int ts ) { if( TiltSensor_data.detected == 0 ) TiltSensor_detect(); if( TiltSensor_data.detected == -1 ) return -1; TiltSensor_data.refcount++; return 0; } int TiltSensor_close( int ts ) { TiltSensor_data.refcount--; return 0; } const char * TiltSensor_name( int ts ) { return "Apple Sudden Motion Sensor"; } int TiltSensor_read( int ts, int type, int num, HidMsg * msg ) { if( type != CK_HID_ACCELEROMETER ) return -1; if( TiltSensor_data.detected == -1 ) return -1; if( !TiltSensor_do_read() ) return -1; if( TiltSensor_data.dataType == kSMSPowerbookDataType ) { msg->idata[0] = TiltSensor_data.data.powerbook.x; msg->idata[1] = TiltSensor_data.data.powerbook.y; msg->idata[2] = TiltSensor_data.data.powerbook.z; } else if( TiltSensor_data.dataType == kSMSMacBookProDataType ) { msg->idata[0] = TiltSensor_data.data.macbookpro.x; msg->idata[1] = TiltSensor_data.data.macbookpro.y; msg->idata[2] = TiltSensor_data.data.macbookpro.z; } return 0; } #ifdef __CK_HID_WIIREMOTE__ #pragma mark OS X Wii Remote support class Bluetooth_Device : public lockable { public: Bluetooth_Device() { device = NULL; memset( &address, 0, sizeof( address ) ); strncpy( name, "Bluetooth Device", 256 ); interrupt_channel = NULL; control_channel = NULL; disconnect_notification = NULL; type = 0; num = -1; refcount = 0; } virtual ~Bluetooth_Device() { close(); } virtual t_CKINT open() { return -1; } virtual t_CKINT connect() { return -1; } virtual t_CKINT control_init() { return -1; } virtual t_CKINT interrupt_init() { return -1; } virtual t_CKINT disconnect() { return -1; } virtual t_CKINT close() { return -1; } virtual t_CKBOOL is_connected() { return FALSE; } virtual void control_receive( void * data, size_t size ) {}; virtual void interrupt_receive( void * data, size_t size ) {}; virtual void control_send( void * data, size_t size ) {}; virtual void interrupt_send( void * data, size_t size ) {}; IOBluetoothDeviceRef device; BluetoothDeviceAddress address; IOBluetoothL2CAPChannelRef interrupt_channel; IOBluetoothL2CAPChannelRef control_channel; IOBluetoothUserNotificationRef disconnect_notification; char name[256]; t_CKUINT type; t_CKINT num; t_CKUINT refcount; }; class WiiRemote : public Bluetooth_Device { public: WiiRemote() { force_feedback_enabled = FALSE; motion_sensor_enabled = FALSE; ir_sensor_enabled = FALSE; led1 = led2 = led3 = led4 = FALSE; speaker_enabled = FALSE; timer = NULL; audio_buffer = NULL; memset( &buttons, 0, sizeof( buttons ) ); memset( &accels, 0, sizeof( accels ) ); memset( &ir, 0xff, sizeof( ir ) ); } virtual t_CKINT open(); virtual t_CKINT connect(); virtual t_CKINT control_init(); virtual t_CKINT disconnect(); virtual t_CKINT close(); virtual t_CKBOOL is_connected(); virtual void control_receive( void * data, size_t size ); virtual void interrupt_receive( void * data, size_t size ); virtual void control_send( const void * data, size_t size ); virtual void write_memory( const void * data, size_t size, unsigned long address ); virtual void enable_force_feedback( t_CKBOOL enable ); virtual void enable_motion_sensor( t_CKBOOL enable ); virtual void enable_ir_sensor( t_CKBOOL enable ); virtual void enable_leds( t_CKBOOL l1, t_CKBOOL l2, t_CKBOOL l3, t_CKBOOL l4 ); virtual void set_led( t_CKUINT led, t_CKBOOL state ); virtual void enable_speaker( t_CKBOOL enable ); CFRunLoopTimerRef timer; CBufferSimple * audio_buffer; virtual void send_audio_data(); t_CKBOOL force_feedback_enabled; t_CKBOOL motion_sensor_enabled; t_CKBOOL ir_sensor_enabled; t_CKBOOL led1, led2, led3, led4; t_CKBOOL speaker_enabled; t_CKBYTE buttons[2]; t_CKBYTE accels[3]; t_CKBYTE ir[12]; enum { ButtonHome = 0, Button1, Button2, ButtonPlus, ButtonMinus, ButtonA, ButtonB, ButtonUp, ButtonRight, ButtonDown, ButtonLeft }; }; bool operator< ( BluetoothDeviceAddress a, BluetoothDeviceAddress b ) { for( int i = 0; i < 6; i++ ) { if( a.data[i] < b.data[i] ) return true; if( a.data[i] > b.data[i] ) return false; } return false; } static xvector< WiiRemote * > * wiiremotes = NULL; /* the user can open a wiimote with any id number he chooses without an error, and will then be sent the appropriate message when that wiimote is connected. The nth wiimote is simply the nth wiimote that chuck hid detects, and since there is absolutely no way to determine how many wiimotes will connect in advance, this number must be left unbounded. To support this, WiiRemote_open will add empty WiiRemotes to wiiremotes with refcount of 1 if it the wiimote its opening isnt there yet, and hope it will be opened at some future time. Thus when discovering wiimotes we have to distinguish between wiimotes that have been discovered and wiimotes that have been opened but have not yet been discovered. all wiimotes with indices less than g_wr_next_real_wiimote have actually been discovered, and anything at or above that index in wiiremotes has not actually been discovered, but (if its non-NULL) has been opened. */ static xvector< WiiRemote * >::size_type g_next_real_wiimote = 0; static map< BluetoothDeviceAddress, WiiRemote * > * wr_addresses = NULL; static t_CKBOOL g_bt_query_active = FALSE; // is a query currently active? void Bluetooth_device_connected( void * userRefCon, IOBluetoothDeviceRef deviceRef, IOReturn status ) { if( status == noErr ) ( ( Bluetooth_Device * ) userRefCon )->connect(); else EM_log( CK_LOG_WARNING, "hid: error: opening Wii Remote Controller connection" ); } void Bluetooth_device_control_event( IOBluetoothL2CAPChannelRef l2capChannel, void * refCon, IOBluetoothL2CAPChannelEvent * event ) { switch( event->eventType ) { case kIOBluetoothL2CAPChannelEventTypeOpenComplete: ( ( Bluetooth_Device * ) refCon )->control_init(); break; case kIOBluetoothL2CAPChannelEventTypeData: ( ( Bluetooth_Device * ) refCon )->control_receive( event->u.data.dataPtr, event->u.data.dataSize ); break; case kIOBluetoothL2CAPChannelEventTypeWriteComplete: if( event->status != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: writing data to control L2CAP channel for '%s'", ( ( Bluetooth_Device * ) refCon )->name ); } break; case kIOBluetoothL2CAPChannelEventTypeClosed: EM_log( CK_LOG_FINE, "hid: error: control L2CAP channel for '%s' closed", ( ( Bluetooth_Device * ) refCon )->name ); break; } } void Bluetooth_device_interrupt_event( IOBluetoothL2CAPChannelRef l2capChannel, void * refCon, IOBluetoothL2CAPChannelEvent * event ) { switch( event->eventType ) { case kIOBluetoothL2CAPChannelEventTypeData: ( ( Bluetooth_Device * ) refCon )->control_receive( event->u.data.dataPtr, event->u.data.dataSize ); break; } } void Bluetooth_device_disconnected( void * userRefCon, IOBluetoothUserNotificationRef inRef, IOBluetoothObjectRef objectRef ) { ( ( Bluetooth_Device * ) userRefCon )->disconnect(); } void WiiRemote_send_audio_data( CFRunLoopTimerRef timer, void *info ) { WiiRemote * wr = ( WiiRemote * ) info; wr->send_audio_data(); } t_CKINT WiiRemote::open() { // see if its already connected, reconnect if so if( IOBluetoothDeviceIsConnected( device ) ) { if( IOBluetoothDeviceCloseConnection( device ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: closing Wii Remote Controller connection" ); return -1; } } if( IOBluetoothDeviceOpenConnection( device, Bluetooth_device_connected, this ) != noErr) { EM_log( CK_LOG_WARNING, "hid: error: opening Wii Remote Controller connection" ); return -1; } return 0; } t_CKINT WiiRemote::connect() { disconnect_notification = IOBluetoothDeviceRegisterForDisconnectNotification( device, Bluetooth_device_disconnected, this ); if( disconnect_notification == NULL ) { EM_log( CK_LOG_WARNING, "hid: error: registering for Wii Remote Controller disconnection notification" ); return -1; } if( IOBluetoothDeviceOpenL2CAPChannelAsync( device, &control_channel, 17, Bluetooth_device_control_event, this ) != kIOReturnSuccess ) { EM_log( CK_LOG_WARNING, "hid: error: opening Wii Remote Controller L2CAP connection" ); return -1; } //fprintf( stderr, "l2cap control channel ref: 0x%x\n", control_channel ); if( IOBluetoothDeviceOpenL2CAPChannelAsync( device, &interrupt_channel, 19, Bluetooth_device_interrupt_event, this ) != kIOReturnSuccess ) { EM_log( CK_LOG_WARNING, "hid: error: opening Wii Remote Controller L2CAP connection" ); return -1; } return 0; } t_CKINT WiiRemote::control_init() { enable_motion_sensor( TRUE ); enable_ir_sensor( TRUE ); enable_force_feedback( FALSE ); usleep( 1000 ); enable_leds( ( num % 4 ) == 0, ( ( num - 1 ) % 4 ) == 0, ( ( num - 2 ) % 4 ) == 0, ( ( num - 3 ) % 4 ) == 0 ); usleep( 1000 ); enable_speaker( TRUE ); HidMsg msg; msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = CK_HID_DEVICE_CONNECTED; HidInManager::push_message( msg ); return 0; } t_CKINT WiiRemote::disconnect() { if( interrupt_channel ) { IOBluetoothL2CAPChannelCloseChannel( interrupt_channel ); IOBluetoothObjectRelease( interrupt_channel ); interrupt_channel = NULL; } if( control_channel ) { IOBluetoothL2CAPChannelCloseChannel( control_channel ); IOBluetoothObjectRelease( control_channel ); control_channel = NULL; } if( device ) { IOBluetoothDeviceCloseConnection( device ); IOBluetoothObjectRelease( device ); device = NULL; } if( disconnect_notification ) { IOBluetoothUserNotificationUnregister( disconnect_notification ); disconnect_notification = NULL; } HidMsg msg; msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = CK_HID_DEVICE_DISCONNECTED; HidInManager::push_message( msg ); return 0; } t_CKINT WiiRemote::close() { if( is_connected() ) disconnect(); return 0; } t_CKBOOL WiiRemote::is_connected() { if( device == NULL ) return FALSE; return TRUE; } void WiiRemote::control_receive( void * data, size_t size ) { unsigned char * d = ( unsigned char * ) data; HidMsg msg; if( ( d[1] & 0xf0 ) == 0x30 ) { /* buttons */ if( ( d[3] & 0x80 ) ^ ( buttons[1] & 0x80 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x80 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonHome; HidInManager::push_message( msg ); msg.clear(); } if( ( d[3] & 0x02 ) ^ ( buttons[1] & 0x02 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x02 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = Button1; HidInManager::push_message( msg ); msg.clear(); } if( ( d[3] & 0x01 ) ^ ( buttons[1] & 0x01 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x01 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = Button2; HidInManager::push_message( msg ); msg.clear(); } if( ( d[2] & 0x10 ) ^ ( buttons[0] & 0x10 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[2] & 0x10 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonPlus; HidInManager::push_message( msg ); msg.clear(); } if( ( d[3] & 0x10 ) ^ ( buttons[1] & 0x10 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x10 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonMinus; HidInManager::push_message( msg ); msg.clear(); } if( ( d[3] & 0x08 ) ^ ( buttons[1] & 0x08 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x08 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonA; HidInManager::push_message( msg ); msg.clear(); } if( ( d[3] & 0x04 ) ^ ( buttons[1] & 0x04 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[3] & 0x04 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonB; HidInManager::push_message( msg ); msg.clear(); } if( ( d[2] & 0x08 ) ^ ( buttons[0] & 0x08 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[2] & 0x08 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonUp; HidInManager::push_message( msg ); msg.clear(); } if( ( d[2] & 0x02 ) ^ ( buttons[0] & 0x02 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[2] & 0x02 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonRight; HidInManager::push_message( msg ); msg.clear(); } if( ( d[2] & 0x04 ) ^ ( buttons[0] & 0x04 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[2] & 0x04 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonDown; HidInManager::push_message( msg ); msg.clear(); } if( ( d[2] & 0x01 ) ^ ( buttons[0] & 0x01 ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = ( d[2] & 0x01 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = ButtonLeft; HidInManager::push_message( msg ); msg.clear(); } memcpy( buttons, d + 2, sizeof( buttons ) ); /* accelerometers */ if( d[1] & 0x01 ) { if( d[4] ^ accels[0] || d[5] ^ accels[1] || d[6] ^ accels[2] ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = CK_HID_ACCELEROMETER; msg.eid = 0; msg.idata[0] = d[4]; msg.idata[1] = d[5]; msg.idata[2] = d[6]; HidInManager::push_message( msg ); msg.clear(); } memcpy( accels, d + 4, sizeof( accels ) ); } /* ir sensor */ if( d[1] & 0x02 ) { unsigned i; for( i = 0; i < 4; i++ ) { if( ( d[7 + i * 3] ^ ir[i * 3] || d[7 + i * 3 + 1] ^ ir[i * 3 + 1] || d[7 + i * 3 + 2] ^ ir[i * 3 + 2] ) && ( d[7 + i * 3] != 0xff ) && ( d[7 + i * 3 + 1] != 0xff ) && ( d[7 + i * 3 + 2] != 0xff ) ) { msg.device_num = num; msg.device_type = CK_HID_DEV_WIIREMOTE; msg.type = CK_HID_WIIREMOTE_IR; msg.eid = i; // x msg.idata[0] = d[7 + 3 * i] + ( ( d[7 + 3 * i + 2] << 4 ) & 0x300 ); // y msg.idata[1] = d[7 + 3 * i + 1] + ( ( d[7 + 3 * i + 2] << 2 ) & 0x300 ); // size msg.idata[2] = d[7 + 3 * i + 2] & 0xffff; HidInManager::push_message( msg ); msg.clear(); } } memcpy( ir, d + 7, sizeof( ir ) ); } } } void WiiRemote::interrupt_receive( void * data, size_t size ) { } void WiiRemote::control_send( const void * data, size_t size ) { assert( size <= 22 ); unsigned char buf[23]; memset( buf, 0, 23 ); buf[0] = 0x52; memcpy( buf+1, data, size ); size++; //printf( "send (%i):", size ); //for( int i = 0; i < size; i++ ) // printf( " %02x", buf[i] ); //printf( "\n" ); //fprintf( stderr, "l2cap control channel ref: 0x%x\n", control_channel ); IOReturn result; result = IOBluetoothL2CAPChannelWriteSync( control_channel, buf, size ); //IOReturn result = IOBluetoothL2CAPChannelWriteAsync( control_channel, buf, size, NULL ); if( result != kIOReturnSuccess ) EM_log( CK_LOG_WARNING, "hid: error: sending data to Wii Remote Controller %i (error 0x%x)", num, result ); } void WiiRemote::write_memory( const void * data, size_t size, unsigned long address ) { assert( size <= 16 ); unsigned char cmd[22]; memset( cmd, 0, 22 ); memcpy( cmd + 6, data, size ); cmd[0] = 0x16; cmd[1] = ( address >> 24 ) & 0xff; cmd[2] = ( address >> 16 ) & 0xff; cmd[3] = ( address >> 8 ) & 0xff; cmd[4] = address & 0xff; cmd[5] = size; if( force_feedback_enabled ) cmd[1] |= 0x01; control_send( cmd, 22 ); } void WiiRemote::enable_force_feedback( t_CKBOOL enable ) { force_feedback_enabled = enable; unsigned char cmd[] = { 0x13, 0x00 }; if( enable ) cmd[1] |= 0x01; if( ir_sensor_enabled ) cmd[1] |= 0x04; control_send( cmd, 2 ); } void WiiRemote::enable_motion_sensor( t_CKBOOL enable ) { motion_sensor_enabled = enable; unsigned char cmd[] = { 0x12, 0x00, 0x30 }; if( motion_sensor_enabled ) cmd[2] |= 0x01; if( ir_sensor_enabled ) cmd[2] |= 0x02; if( force_feedback_enabled ) cmd[1] |= 0x01; control_send( cmd, 3 ); } void WiiRemote::enable_ir_sensor( t_CKBOOL enable ) { ir_sensor_enabled = enable; enable_motion_sensor( motion_sensor_enabled ); enable_force_feedback( force_feedback_enabled ); unsigned char cmd[] = { 0x1a, 0x00 }; if( ir_sensor_enabled ) cmd[1] |= 0x04; if( force_feedback_enabled ) cmd[1] |= 0x01; control_send( cmd, 2 ); if( ir_sensor_enabled ) { unsigned char en0[] = { 0x01 }; write_memory( en0, 1, 0x04b00030 ); //usleep(10000); unsigned char en[] = { 0x08 }; write_memory( en, 1, 0x04b00030 ); //usleep(10000); unsigned char sensitivity_block1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0xc0 }; write_memory( sensitivity_block1, 9, 0x04b00000 ); //usleep(10000); unsigned char sensitivity_block2[] = { 0x40, 0x00 }; write_memory( sensitivity_block2, 2, 0x04b0001a ); //usleep(10000); unsigned char mode[] = { 0x03 }; write_memory( mode, 1, 0x04b00033 ); // usleep(10000); unsigned char what[] = { 0x08 }; write_memory( what, 1, 0x04b00030 ); //usleep(10000); } } void WiiRemote::set_led( t_CKUINT led, t_CKBOOL state ) { switch( led ) { case 0: led1 = state; break; case 1: led2 = state; break; case 2: led3 = state; break; case 3: led4 = state; break; } enable_leds( led1, led2, led3, led4 ); } void WiiRemote::enable_leds( t_CKBOOL l1, t_CKBOOL l2, t_CKBOOL l3, t_CKBOOL l4 ) { led1 = l1; led2 = l2; led3 = l3; led4 = l4; unsigned char cmd[] = { 0x11, 0x00 }; if( force_feedback_enabled ) cmd[1] |= 0x01; if( l1 ) cmd[1] |= 0x10; if( l2 ) cmd[1] |= 0x20; if( l3 ) cmd[1] |= 0x40; if( l4 ) cmd[1] |= 0x80; control_send( cmd, 2 ); } void WiiRemote::enable_speaker( t_CKBOOL enable ) { speaker_enabled = enable; if( speaker_enabled ) { // enable speaker unsigned char cmd[] = { 0x14, 0x04 }; if( force_feedback_enabled ) cmd[1] |= 0x01; control_send( cmd, 2 ); // mute unsigned char mute[] = { 0x19, 0x04 }; if( force_feedback_enabled ) mute[1] |= 0x01; control_send( mute, 2 ); unsigned char mem1[] = { 0x01 }; write_memory( mem1, 1, 0x04a20009 ); unsigned char mem2[] = { 0x08 }; write_memory( mem2, 1, 0x04a20001 ); // config unsigned char config[] = { 0x00, 0x00, 0x00, 0x0c, 0x40, 0x00, 0x00 }; // description // byte 0: unknown // 1: unknown // 2: unknown // 3: sample rate -{ 0x0B = 4200 Hz // 0x0C = 3920 Hz // 0x0D = 3640 Hz // 0x0E = 3360 Hz // 0x0F = 3080 Hz // 4: speaker volume // 5: unknown // 6: unknown write_memory( config, 7, 0x04a20001 ); unsigned char mem3[] = { 0x01 }; write_memory( mem3, 1, 0x04a20008 ); // unmute unsigned char unmute[] = { 0x19, 0x00 }; if( force_feedback_enabled ) unmute[1] |= 0x01; control_send( unmute, 2 ); // initialize audio buffer, if necessary if( audio_buffer == NULL ) { audio_buffer = new CBufferSimple; audio_buffer->initialize( 20 * 5, sizeof( SAMPLE ) ); } // set up audio timer callback, if necessary if( timer == NULL ) { CFRunLoopTimerContext timerContext = { 0, this, NULL, NULL, NULL }; timer = CFRunLoopTimerCreate( NULL, CFAbsoluteTimeGetCurrent(), 1.0 / 3920.0, 0, 0, WiiRemote_send_audio_data, &timerContext ); CFRunLoopAddTimer( rlHid, timer, kCFRunLoopChuckHidMode ); } } } void WiiRemote::send_audio_data() { unsigned char cmd[] = { 0x18, ( 20 << 3 ), 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; if( force_feedback_enabled ) cmd[1] |= 0x01; control_send( cmd, 22 ); } void Bluetooth_inquiry_device_found( void * userRefCon, IOBluetoothDeviceInquiryRef inquiryRef, IOBluetoothDeviceRef deviceRef ) { CFStringRef device_name = IOBluetoothDeviceGetName( deviceRef ); const BluetoothDeviceAddress * address = IOBluetoothDeviceGetAddress( deviceRef ); if( device_name == NULL ) return; // is device Nintendo Wii Remote controller? if( CFStringCompare( device_name, CFSTR( "Nintendo RVL-CNT-01" ), 0 ) == 0 ) { // has this already been detected? if( wr_addresses->find( *address ) == wr_addresses->end() ) { WiiRemote * wr; if( g_next_real_wiimote >= wiiremotes->size() ) { wr = new WiiRemote; wiiremotes->push_back( wr ); } else if( ( *wiiremotes )[g_next_real_wiimote] == NULL ) { wr = new WiiRemote; ( *wiiremotes )[g_next_real_wiimote] = wr; } else { wr = ( *wiiremotes )[g_next_real_wiimote]; } // set member data wr->device = deviceRef; memcpy( &wr->address, address, sizeof( BluetoothDeviceAddress ) ); strncpy( wr->name, "Nintendo RVL-CNT-01", 256 ); wr->num = g_next_real_wiimote; wr->type = CK_HID_DEV_WIIREMOTE; ( *wr_addresses )[wr->address] = wr; EM_log( CK_LOG_INFO, "hid: found Wii Remote Controller" ); if( wr->refcount ) wr->open(); g_next_real_wiimote++; } else if( !( *wr_addresses )[*address]->is_connected() ) { WiiRemote * wr = ( *wr_addresses )[*address]; if( wr->refcount ) wr->open(); } } else { EM_log( CK_LOG_INFO, "hid: found bluetooth device" ); } } void Bluetooth_inquiry_complete( void * userRefCon, IOBluetoothDeviceInquiryRef inquiryRef, IOReturn error, Boolean aborted ) { g_bt_query_active = FALSE; } int WiiRemote_query() { EM_log( CK_LOG_INFO, "hid: performing bluetooth query" ); if( g_bt_query_active ) return 0; if( IOBluetoothLocalDeviceAvailable() == FALSE ) { EM_log( CK_LOG_WARNING, "hid: error: bluetooth unavailable" ); return -1; } IOBluetoothDeviceInquiryRef btDeviceInquiry = IOBluetoothDeviceInquiryCreateWithCallbackRefCon( NULL ); if( btDeviceInquiry == NULL ) { EM_log( CK_LOG_WARNING, "hid: error: creating bluetooth device inquiry" ); return -1; } if( IOBluetoothDeviceInquirySetDeviceFoundCallback( btDeviceInquiry, Bluetooth_inquiry_device_found ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: setting bluetooth device inquiry callback" ); return -1; } if( IOBluetoothDeviceInquirySetCompleteCallback( btDeviceInquiry, Bluetooth_inquiry_complete ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: setting bluetooth device inquiry completion callback" ); return -1; } if( IOBluetoothDeviceInquirySetUpdateNewDeviceNames( btDeviceInquiry, TRUE ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: setting bluetooth device inquiry name update flag" ); return -1; } if( IOBluetoothDeviceInquirySetInquiryLength( btDeviceInquiry, 20 ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: setting bluetooth inquiry length" ); return -1; } if( IOBluetoothDeviceInquiryStart( btDeviceInquiry ) != noErr ) { EM_log( CK_LOG_WARNING, "hid: error: starting bluetooth device inquiry" ); return -1; } g_bt_query_active = TRUE; return 0; } /* -- WiiRemote inter-thread communication -- Every IOBluetooth function needs to be called from the HID thread because none of it is thread safe, and it also requires a CFRunLoop to be running at some point. So, WiiRemote_open and _close, which are called from the VM thread, put open and close messages into a thread-safe circular buffer and then signal the hid thread to indicate that new info is available on the cbuf. The hid thread will then process any pending open/close messages in the cbuf. send messages now also are carried out in the hid thread through this mechanism. */ struct WiiRemoteOp { enum { open, close, send } op; int index; }; static CBufferSimple * WiiRemoteOp_cbuf = NULL; static CBufferSimple * WiiRemoteOp_msgbuf = NULL; static void WiiRemote_cfrl_callback( void * info ) { WiiRemoteOp wro; HidMsg msg; t_CKBOOL do_query = FALSE; while( WiiRemoteOp_cbuf->get( &wro, 1 ) ) { switch( wro.op ) { case WiiRemoteOp::open: // does it exist already? if( wro.index < wiiremotes->size() ) // yes { // is the device connected? if( !( *wiiremotes )[wro.index]->is_connected() ) // no, so do a query do_query = TRUE; } else // no, so create it { while( wro.index > wiiremotes->size() ) wiiremotes->push_back( NULL ); wiiremotes->push_back( new WiiRemote ); do_query = TRUE; } ( *wiiremotes )[wro.index]->refcount++; break; case WiiRemoteOp::close: if( wro.index < wiiremotes->size() ) { if( --( *wiiremotes )[wro.index]->refcount == 0 ) ( *wiiremotes )[wro.index]->close(); } break; case WiiRemoteOp::send: if( WiiRemoteOp_msgbuf->get( &msg, 1 ) ) { // double-check remote number for validity if( wro.index < 0 || wro.index >= wiiremotes->size() || ( *wiiremotes )[wro.index] == NULL || !( *wiiremotes )[wro.index]->is_connected() ) { // report failure HidInManager::push_message( msg ); break; } switch( msg.type ) { case CK_HID_LED: if( msg.eid < 0 || msg.eid >= 4 ) { // report failure HidInManager::push_message( msg ); break; } ( *wiiremotes )[wro.index]->set_led( msg.eid, msg.idata[0] ); break; case CK_HID_FORCE_FEEDBACK: ( *wiiremotes )[wro.index]->enable_force_feedback( msg.idata[0] ); break; } } break; } } if( do_query ) WiiRemote_query(); } static void WiiRemote_signal() { if( cfrlWiiRemoteSource && rlHid ) { CFRunLoopSourceSignal( cfrlWiiRemoteSource ); CFRunLoopWakeUp( rlHid ); } } #endif // __CK_HID_WIIREMOTE void WiiRemote_init() { #ifdef __CK_HID_WIIREMOTE__ Hid_init2(); wiiremotes = new xvector< WiiRemote * >; wr_addresses = new map< BluetoothDeviceAddress, WiiRemote * >; WiiRemoteOp_cbuf = new CBufferSimple; WiiRemoteOp_cbuf->initialize( 20, sizeof( WiiRemoteOp ) ); WiiRemoteOp_msgbuf = new CBufferSimple; WiiRemoteOp_msgbuf->initialize( 100, sizeof( HidMsg ) ); #endif // __CK_HID_WIIREMOTE } void WiiRemote_poll() { } void WiiRemote_quit() { #ifdef __CK_HID_WIIREMOTE__ for( xvector< WiiRemote * >::size_type i = 0; i < wiiremotes->size(); i++ ) { if( ( *wiiremotes )[i] ) SAFE_DELETE( ( *wiiremotes )[i] ); } SAFE_DELETE( wiiremotes ); SAFE_DELETE( wr_addresses ); SAFE_DELETE( WiiRemoteOp_cbuf ); Hid_quit2(); #endif // __CK_HID_WIIREMOTE__ } int WiiRemote_count() { #ifdef __CK_HID_WIIREMOTE__ return wiiremotes->size(); #else return 0; #endif // __CK_HID_WIIREMOTE__ } int WiiRemote_open( int wr ) { #ifdef __CK_HID_WIIREMOTE__ WiiRemoteOp wro; wro.op = WiiRemoteOp::open; wro.index = wr; WiiRemoteOp_cbuf->put( &wro, 1 ); WiiRemote_signal(); return 0; #else return -1; #endif // __CK_HID_WIIREMOTE__ } int WiiRemote_close( int wr ) { #ifdef __CK_HID_WIIREMOTE__ WiiRemoteOp wro; wro.op = WiiRemoteOp::close; wro.index = wr; WiiRemoteOp_cbuf->put( &wro, 1 ); WiiRemote_signal(); return 0; #else return -1; #endif // __CK_HID_WIIREMOTE__ } int WiiRemote_send( int wr, const HidMsg * msg ) { #ifdef __CK_HID_WIIREMOTE__ wiiremotes->lock(); if( wr < 0 || wr >= wiiremotes->size() ) { wiiremotes->unlock(); return -1; } WiiRemote * wiiremote = ( *wiiremotes )[wr]; wiiremotes->unlock(); if( wiiremote == NULL ) return -1; wiiremote->lock(); if( !wiiremote->is_connected() ) { wiiremote->unlock(); return -1; } wiiremote->unlock(); WiiRemoteOp_msgbuf->put( ( void * )msg, 1 ); WiiRemoteOp wro; wro.op = WiiRemoteOp::send; wro.index = wr; WiiRemoteOp_cbuf->put( &wro, 1 ); WiiRemote_signal(); return 0; #else return -1; #endif } const char * WiiRemote_name( int wr ) { #ifdef __CK_HID_WIIREMOTE__ return "Nintendo Wii Remote"; #else return " "; #endif // __CK_HID_WIIREMOTE__ } #elif ( defined( __PLATFORM_WIN32__ ) || defined( __WINDOWS_PTHREAD__ ) ) && !defined( USE_RAWINPUT ) /***************************************************************************** Windows general HID support *****************************************************************************/ #pragma mark Windows general HID support #include #define DIRECTINPUT_VERSION 0x0500 #include /* for performance, we use device event notifications to tell us when a device has new data. However, serial devices don't seem to support event notification, so we have to fall back to the periodic sleeping and polling. g_wait_function is usually set to call WaitForSingleObject (wait for event notification), but devices for which SetEventNotification fails will replace it with a wrapper around usleep. */ static HANDLE g_device_event = NULL; static void (*g_wait_function)() = NULL; static void Hid_wait_usleep() { usleep( 10 ); } static void Hid_wait_event() { WaitForSingleObject( g_device_event, INFINITE ); } void Hid_init() { if( g_device_event != NULL ) return; g_device_event = CreateEvent( NULL, FALSE, FALSE, NULL ); if( g_device_event == NULL ) EM_log( CK_LOG_SEVERE, "hid: error: unable to create event (win32 error %i)", GetLastError() ); g_wait_function = Hid_wait_event; } void Hid_poll() { g_wait_function(); Joystick_poll(); Keyboard_poll(); Mouse_poll(); } void Hid_quit() { SetEvent( g_device_event ); /*if( g_device_event != NULL ) { CloseHandle( g_device_event ); g_device_event = NULL; }*/ } /***************************************************************************** Windows joystick support *****************************************************************************/ #pragma mark Windows joystick support static LPDIRECTINPUT lpdi = NULL; struct win32_joystick { win32_joystick() { lpdiJoystick = NULL; refcount = 0; needs_close = FALSE; strncpy( name, "Joystick", MAX_PATH ); memset( &last_state, 0, sizeof( last_state ) ); memset( &caps, 0, sizeof( caps ) ); caps.dwSize = sizeof( DIDEVCAPS ); } LPDIRECTINPUTDEVICE2 lpdiJoystick; DIJOYSTATE2 last_state; DIDEVCAPS caps; char name[MAX_PATH]; t_CKUINT refcount; t_CKBOOL needs_close; }; const static LONG axis_min = -32767; const static LONG axis_max = 32767; static vector< win32_joystick * > * joysticks; static BOOL CALLBACK DIEnumJoystickProc( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) { GUID guid = lpddi->guidInstance; win32_joystick * js = new win32_joystick; EM_log( CK_LOG_INFO, "found %s", lpddi->tszProductName ); strncpy( js->name, lpddi->tszProductName, MAX_PATH ); if( lpdi->CreateDevice( guid, ( LPDIRECTINPUTDEVICE * )&js->lpdiJoystick, NULL ) != DI_OK ) { delete js; return DIENUM_CONTINUE; } joysticks->push_back( js ); return DIENUM_CONTINUE; } static BOOL CALLBACK DIEnumJoystickObjectsProc( LPCDIDEVICEOBJECTINSTANCE lpdidoi, LPVOID pvRef ) { LPDIRECTINPUTDEVICE lpdiJoystick = ( LPDIRECTINPUTDEVICE ) pvRef; DIPROPRANGE diprg; // set axis minimum and maximum range diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = lpdidoi->dwType; diprg.lMin = axis_min; diprg.lMax = axis_max; if( lpdiJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) != DI_OK ) { } return DIENUM_CONTINUE; } void Joystick_init() { if( joysticks != NULL ) return; EM_log( CK_LOG_INFO, "initializing joystick" ); EM_pushlog(); HINSTANCE hInstance = GetModuleHandle( NULL ); if( lpdi == NULL ) { if( DirectInputCreate( hInstance, DIRECTINPUT_VERSION, &lpdi, NULL) != DI_OK ) { lpdi = NULL; EM_log( CK_LOG_SEVERE, "error: unable to initialize DirectInput, initialization failed" ); EM_poplog(); return; } } joysticks = new vector< win32_joystick * >; if( lpdi->EnumDevices( DIDEVTYPE_JOYSTICK, DIEnumJoystickProc, NULL, DIEDFL_ATTACHEDONLY ) != DI_OK ) { delete joysticks; joysticks = NULL; lpdi->Release(); lpdi = NULL; EM_log( CK_LOG_SEVERE, "error: unable to enumerate devices, initialization failed" ); EM_poplog(); return; } EM_poplog(); } t_CKINT Joystick_translate_POV( DWORD v ) { #define CK_POV_CENTER 0 #define CK_POV_UP 1 #define CK_POV_RIGHT 2 #define CK_POV_DOWN 4 #define CK_POV_LEFT 8 #define CK_POV_UP_LBORDER 29250 #define CK_POV_UP_RBORDER 6750 #define CK_POV_RIGHT_LBORDER 2250 #define CK_POV_RIGHT_RBORDER 15750 #define CK_POV_DOWN_LBORDER 11250 #define CK_POV_DOWN_RBORDER 24750 #define CK_POV_LEFT_LBORDER 20250 #define CK_POV_LEFT_RBORDER 33750 t_CKINT r = 0; if( LOWORD(v) == 0xffff ) return CK_POV_CENTER; if( v > CK_POV_UP_LBORDER || v < CK_POV_UP_RBORDER ) r |= CK_POV_UP; if( v > CK_POV_RIGHT_LBORDER && v < CK_POV_RIGHT_RBORDER ) r |= CK_POV_RIGHT; if( v > CK_POV_DOWN_LBORDER && v < CK_POV_DOWN_RBORDER ) r |= CK_POV_DOWN; if( v > CK_POV_LEFT_LBORDER && v < CK_POV_LEFT_RBORDER ) r |= CK_POV_LEFT; return r; } void Joystick_poll() { if( !joysticks ) return; win32_joystick * joystick; HidMsg msg; vector< win32_joystick * >::size_type i, len = joysticks->size(); int j; for( i = 0; i < len; i++ ) { joystick = joysticks->at( i ); if( joystick->refcount ) { // TODO: convert this to buffered input, or maybe notifications DIJOYSTATE2 state; joystick->lpdiJoystick->Poll(); if( joystick->lpdiJoystick->GetDeviceState( sizeof( DIJOYSTATE2 ), &state ) != DI_OK ) { EM_log( CK_LOG_WARNING, "joystick: GetDeviceState failed for %s", joystick->name ); continue; } if( state.lX != joystick->last_state.lX ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 0; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lX)/((float)axis_max); HidInManager::push_message( msg ); } if( state.lY != joystick->last_state.lY ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 1; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lY)/((float)axis_max); HidInManager::push_message( msg ); } if( state.lZ != joystick->last_state.lZ ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 2; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lZ)/((float)axis_max); HidInManager::push_message( msg ); } if( state.lRx != joystick->last_state.lRx ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 3; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lRx)/((float)axis_max); HidInManager::push_message( msg ); } if( state.lRy != joystick->last_state.lRy ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 4; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lRy)/((float)axis_max); HidInManager::push_message( msg ); } if( state.lRz != joystick->last_state.lRz ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 5; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.lRz)/((float)axis_max); HidInManager::push_message( msg ); } for( j = 0; j < 2; j++ ) { if( state.rglSlider[j] != joystick->last_state.rglSlider[j] ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = 5 + j; msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((float)state.rglSlider[j])/((float)axis_max); HidInManager::push_message( msg ); } } for( j = 0; j < joystick->caps.dwPOVs && j < 4; j++ ) { if( state.rgdwPOV[j] != joystick->last_state.rgdwPOV[j] ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = j; msg.type = CK_HID_JOYSTICK_HAT; msg.idata[0] = Joystick_translate_POV( state.rgdwPOV[j] ); msg.fdata[0] = (t_CKFLOAT)state.rgdwPOV[j]; HidInManager::push_message( msg ); } } for( j = 0; j < joystick->caps.dwButtons && j < 128; j++ ) { if( ( state.rgbButtons[j] & 0x80 ) ^ ( joystick->last_state.rgbButtons[j] & 0x80 ) ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_JOYSTICK; msg.eid = j; msg.type = ( state.rgbButtons[j] & 0x80 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = ( state.rgbButtons[j] & 0x80 ) ? 1 : 0; HidInManager::push_message( msg ); } } joystick->last_state = state; } else if( joystick->needs_close ) { joystick->needs_close = FALSE; joystick->lpdiJoystick->Unacquire(); joystick->lpdiJoystick->SetEventNotification( NULL ); } } } void Joystick_quit() { if( joysticks ) { win32_joystick * joystick; vector< win32_joystick * >::size_type i, len = joysticks->size(); for( i = 0; i < len; i++ ) { joystick = joysticks->at( i ); if( joystick->refcount > 0 || joystick->needs_close) { joystick->needs_close = FALSE; joystick->refcount = 0; joystick->lpdiJoystick->Unacquire(); joystick->lpdiJoystick->SetEventNotification( NULL ); } joystick->lpdiJoystick->Release(); delete joystick; } delete joysticks; joysticks = NULL; } if( lpdi ) { lpdi->Release(); lpdi = NULL; } } int Joystick_count() { if( !joysticks ) return 0; return joysticks->size(); } int Joystick_open( int js ) { if( !joysticks || js < 0 || js >= joysticks->size() ) return -1; win32_joystick * joystick = joysticks->at( js ); if( joystick->refcount == 0 ) { if( joystick->lpdiJoystick->EnumObjects( DIEnumJoystickObjectsProc, joystick->lpdiJoystick, DIDFT_AXIS ) != DI_OK ) { return -1; } if( joystick->lpdiJoystick->GetCapabilities( &joystick->caps ) != DI_OK ) { return -1; } if( joystick->lpdiJoystick->SetDataFormat( &c_dfDIJoystick2 ) != DI_OK ) { return -1; } if( joystick->lpdiJoystick->SetEventNotification( g_device_event ) != DI_OK ) { // fallback to sleep+poll mode g_wait_function = Hid_wait_usleep; SetEvent( g_device_event ); } if( joystick->lpdiJoystick->Acquire() != DI_OK ) { joystick->lpdiJoystick->SetEventNotification( NULL ); return -1; } } joystick->refcount++; return 0; } int Joystick_close( int js ) { if( !joysticks || js < 0 || js >= joysticks->size() ) return -1; win32_joystick * joystick = joysticks->at( js ); joystick->refcount--; if( joystick->refcount < 1 ) joystick->needs_close = TRUE; return 0; } const char * Joystick_name( int js ) { if( !joysticks || js < 0 || js >= joysticks->size() ) return NULL; return joysticks->at( js )->name; } /***************************************************************************** Windows keyboard support *****************************************************************************/ #pragma mark Windows keyboards support #define DINPUT_KEYBUFFER_SIZE 256 struct win32_keyboard { win32_keyboard() { lpdiKeyboard = NULL; refcount = 0; needs_close = FALSE; strncpy( name, "Keyboard", MAX_PATH ); memset( &last_state, 0, DINPUT_KEYBUFFER_SIZE ); } LPDIRECTINPUTDEVICE2 lpdiKeyboard; char last_state[DINPUT_KEYBUFFER_SIZE]; DIDEVCAPS caps; char name[MAX_PATH]; t_CKUINT refcount; t_CKBOOL needs_close; }; static vector< win32_keyboard * > * keyboards; // table to translate DirectInput keybuffer offsets to ASCII and USB usages // first element is ASCII // second element is USB usage static unsigned short kb_translation_table[DINPUT_KEYBUFFER_SIZE]; static void Keyboard_init_translation_table() { memset( &kb_translation_table, 0, sizeof( kb_translation_table ) ); kb_translation_table[DIK_0] = '0'; kb_translation_table[DIK_0] |= 0x27 << 8; kb_translation_table[DIK_1] = '1'; kb_translation_table[DIK_1] |= 0x1e << 8; kb_translation_table[DIK_2] = '2'; kb_translation_table[DIK_2] |= 0x1f << 8; kb_translation_table[DIK_3] = '3'; kb_translation_table[DIK_3] |= 0x20 << 8; kb_translation_table[DIK_4] = '4'; kb_translation_table[DIK_4] |= 0x21 << 8; kb_translation_table[DIK_5] = '5'; kb_translation_table[DIK_5] |= 0x22 << 8; kb_translation_table[DIK_6] = '6'; kb_translation_table[DIK_6] |= 0x23 << 8; kb_translation_table[DIK_7] = '7'; kb_translation_table[DIK_7] |= 0x24 << 8; kb_translation_table[DIK_8] = '8'; kb_translation_table[DIK_8] |= 0x25 << 8; kb_translation_table[DIK_9] = '9'; kb_translation_table[DIK_9] |= 0x26 << 8; kb_translation_table[DIK_A] = 'A'; kb_translation_table[DIK_A] |= 0x04 << 8; kb_translation_table[DIK_B] = 'B'; kb_translation_table[DIK_B] |= 0x05 << 8; kb_translation_table[DIK_C] = 'C'; kb_translation_table[DIK_C] |= 0x06 << 8; kb_translation_table[DIK_D] = 'D'; kb_translation_table[DIK_D] |= 0x07 << 8; kb_translation_table[DIK_E] = 'E'; kb_translation_table[DIK_E] |= 0x08 << 8; kb_translation_table[DIK_F] = 'F'; kb_translation_table[DIK_F] |= 0x09 << 8; kb_translation_table[DIK_G] = 'G'; kb_translation_table[DIK_G] |= 0x0a << 8; kb_translation_table[DIK_H] = 'H'; kb_translation_table[DIK_H] |= 0x0b << 8; kb_translation_table[DIK_I] = 'I'; kb_translation_table[DIK_I] |= 0x0c << 8; kb_translation_table[DIK_J] = 'J'; kb_translation_table[DIK_J] |= 0x0d << 8; kb_translation_table[DIK_K] = 'K'; kb_translation_table[DIK_K] |= 0x0e << 8; kb_translation_table[DIK_L] = 'L'; kb_translation_table[DIK_L] |= 0x0f << 8; kb_translation_table[DIK_M] = 'M'; kb_translation_table[DIK_M] |= 0x10 << 8; kb_translation_table[DIK_N] = 'N'; kb_translation_table[DIK_N] |= 0x11 << 8; kb_translation_table[DIK_O] = 'O'; kb_translation_table[DIK_O] |= 0x12 << 8; kb_translation_table[DIK_P] = 'P'; kb_translation_table[DIK_P] |= 0x13 << 8; kb_translation_table[DIK_Q] = 'Q'; kb_translation_table[DIK_Q] |= 0x14 << 8; kb_translation_table[DIK_R] = 'R'; kb_translation_table[DIK_R] |= 0x15 << 8; kb_translation_table[DIK_S] = 'S'; kb_translation_table[DIK_S] |= 0x16 << 8; kb_translation_table[DIK_T] = 'T'; kb_translation_table[DIK_T] |= 0x17 << 8; kb_translation_table[DIK_U] = 'U'; kb_translation_table[DIK_U] |= 0x18 << 8; kb_translation_table[DIK_V] = 'V'; kb_translation_table[DIK_V] |= 0x19 << 8; kb_translation_table[DIK_W] = 'W'; kb_translation_table[DIK_W] |= 0x1a << 8; kb_translation_table[DIK_X] = 'X'; kb_translation_table[DIK_X] |= 0x1b << 8; kb_translation_table[DIK_Y] = 'Y'; kb_translation_table[DIK_Y] |= 0x1c << 8; kb_translation_table[DIK_Z] = 'Z'; kb_translation_table[DIK_Z] |= 0x1d << 8; kb_translation_table[DIK_ADD] = '+'; kb_translation_table[DIK_ADD] |= 0x57 << 8; kb_translation_table[DIK_APOSTROPHE] = '\''; kb_translation_table[DIK_APOSTROPHE] |= 0x34 << 8; kb_translation_table[DIK_APPS] = 0; kb_translation_table[DIK_APPS] |= 0x65 << 8; kb_translation_table[DIK_BACK] = '\b'; kb_translation_table[DIK_BACK] |= 0x2a << 8; kb_translation_table[DIK_BACKSLASH] = '\\'; kb_translation_table[DIK_BACKSLASH] |= 0x31 << 8; kb_translation_table[DIK_CAPITAL] = 0; kb_translation_table[DIK_CAPITAL] |= 0x39 << 8; kb_translation_table[DIK_COLON] = ':'; kb_translation_table[DIK_COLON] |= 0x00 << 8; kb_translation_table[DIK_COMMA] = ','; kb_translation_table[DIK_COMMA] |= 0x36 << 8; kb_translation_table[DIK_DECIMAL] = '.'; kb_translation_table[DIK_DECIMAL] |= 0x63 << 8; kb_translation_table[DIK_DELETE] = 0x7f; kb_translation_table[DIK_DELETE] |= 0x4c << 8; kb_translation_table[DIK_DIVIDE] = '/'; kb_translation_table[DIK_DIVIDE] |= 0x54 << 8; kb_translation_table[DIK_DOWN] = 0; kb_translation_table[DIK_DOWN] |= 0x51 << 8; kb_translation_table[DIK_END] = 0; kb_translation_table[DIK_END] |= 0x4d << 8; kb_translation_table[DIK_EQUALS] = '='; kb_translation_table[DIK_EQUALS] |= 0x2e << 8; kb_translation_table[DIK_ESCAPE] = 0x1b; kb_translation_table[DIK_ESCAPE] |= 0x29 << 8; kb_translation_table[DIK_F1] = 0; kb_translation_table[DIK_F1] |= 0x3a << 8; kb_translation_table[DIK_F2] = 0; kb_translation_table[DIK_F2] |= 0x3b << 8; kb_translation_table[DIK_F3] = 0; kb_translation_table[DIK_F3] |= 0x3c << 8; kb_translation_table[DIK_F4] = 0; kb_translation_table[DIK_F4] |= 0x3d << 8; kb_translation_table[DIK_F5] = 0; kb_translation_table[DIK_F5] |= 0x3e << 8; kb_translation_table[DIK_F6] = 0; kb_translation_table[DIK_F6] |= 0x3f << 8; kb_translation_table[DIK_F7] = 0; kb_translation_table[DIK_F7] |= 0x40 << 8; kb_translation_table[DIK_F8] = 0; kb_translation_table[DIK_F8] |= 0x41 << 8; kb_translation_table[DIK_F9] = 0; kb_translation_table[DIK_F9] |= 0x42 << 8; kb_translation_table[DIK_F10] = 0; kb_translation_table[DIK_F10] |= 0x43 << 8; kb_translation_table[DIK_F11] = 0; kb_translation_table[DIK_F11] |= 0x44 << 8; kb_translation_table[DIK_F12] = 0; kb_translation_table[DIK_F12] |= 0x45 << 8; kb_translation_table[DIK_F13] = 0; kb_translation_table[DIK_F13] |= 0x68 << 8; kb_translation_table[DIK_F14] = 0; kb_translation_table[DIK_F14] |= 0x69 << 8; kb_translation_table[DIK_F15] = 0; kb_translation_table[DIK_F15] |= 0x6a << 8; kb_translation_table[DIK_GRAVE] = '`'; kb_translation_table[DIK_GRAVE] |= 0x35 << 8; kb_translation_table[DIK_HOME] = 0; kb_translation_table[DIK_HOME] |= 0x4a << 8; kb_translation_table[DIK_INSERT] = 0; kb_translation_table[DIK_INSERT] |= 0x49 << 8; kb_translation_table[DIK_LBRACKET] = '['; kb_translation_table[DIK_LBRACKET] |= 0x2f << 8; kb_translation_table[DIK_LCONTROL] = 0; kb_translation_table[DIK_LCONTROL] |= 0xe0 << 8; kb_translation_table[DIK_LEFT] = 0; kb_translation_table[DIK_LEFT] |= 0x50 << 8; kb_translation_table[DIK_LMENU] = 0; kb_translation_table[DIK_LMENU] |= 0xe2 << 8; kb_translation_table[DIK_LSHIFT] = 0; kb_translation_table[DIK_LSHIFT] |= 0xe1 << 8; kb_translation_table[DIK_LWIN] = 0; kb_translation_table[DIK_LWIN] |= 0xe3 << 8; kb_translation_table[DIK_MINUS] = '-'; kb_translation_table[DIK_MINUS] |= 0x2d << 8; kb_translation_table[DIK_MULTIPLY] = '*'; kb_translation_table[DIK_MULTIPLY] |= 0x55 << 8; // kb_translation_table[DIK_MUTE] = 0; // kb_translation_table[DIK_MUTE] |= 0x7f; kb_translation_table[DIK_NEXT] = 0; kb_translation_table[DIK_NEXT] |= 0x4e << 8; kb_translation_table[DIK_NUMLOCK] = 0; kb_translation_table[DIK_NUMLOCK] |= 0x53 << 8; kb_translation_table[DIK_NUMPAD0] = '0'; kb_translation_table[DIK_NUMPAD0] |= 0x62 << 8; kb_translation_table[DIK_NUMPAD1] = '1'; kb_translation_table[DIK_NUMPAD1] |= 0x59 << 8; kb_translation_table[DIK_NUMPAD2] = '2'; kb_translation_table[DIK_NUMPAD2] |= 0x5a << 8; kb_translation_table[DIK_NUMPAD3] = '3'; kb_translation_table[DIK_NUMPAD3] |= 0x5b << 8; kb_translation_table[DIK_NUMPAD4] = '4'; kb_translation_table[DIK_NUMPAD4] |= 0x5c << 8; kb_translation_table[DIK_NUMPAD5] = '5'; kb_translation_table[DIK_NUMPAD5] |= 0x5d << 8; kb_translation_table[DIK_NUMPAD6] = '6'; kb_translation_table[DIK_NUMPAD6] |= 0x5e << 8; kb_translation_table[DIK_NUMPAD7] = '7'; kb_translation_table[DIK_NUMPAD7] |= 0x5f << 8; kb_translation_table[DIK_NUMPAD8] = '8'; kb_translation_table[DIK_NUMPAD8] |= 0x60 << 8; kb_translation_table[DIK_NUMPAD9] = '9'; kb_translation_table[DIK_NUMPAD9] |= 0x61 << 8; kb_translation_table[DIK_NUMPADCOMMA] = ','; kb_translation_table[DIK_NUMPADCOMMA] |= 0x85 << 8; kb_translation_table[DIK_NUMPADENTER] = '\n'; kb_translation_table[DIK_NUMPADENTER] |= 0x58 << 8; kb_translation_table[DIK_NUMPADEQUALS] = '='; kb_translation_table[DIK_NUMPADEQUALS] |= 0x67 << 8; kb_translation_table[DIK_PAUSE] = 0; kb_translation_table[DIK_PAUSE] |= 0x48 << 8; kb_translation_table[DIK_PERIOD] = '.'; kb_translation_table[DIK_PERIOD] |= 0x37 << 8; kb_translation_table[DIK_POWER] = 0; kb_translation_table[DIK_POWER] |= 0x66 << 8; kb_translation_table[DIK_PRIOR] = 0; kb_translation_table[DIK_PRIOR] |= 0x4b << 8; kb_translation_table[DIK_RBRACKET] = ']'; kb_translation_table[DIK_RBRACKET] |= 0x30 << 8; kb_translation_table[DIK_RCONTROL] = 0; kb_translation_table[DIK_RCONTROL] |= 0xe4 << 8; kb_translation_table[DIK_RETURN] = '\n'; kb_translation_table[DIK_RETURN] |= 0x28 << 8; kb_translation_table[DIK_RIGHT] = 0; kb_translation_table[DIK_RIGHT] |= 0x4f << 8; kb_translation_table[DIK_RMENU] = 0; kb_translation_table[DIK_RMENU] |= 0xe6 << 8; kb_translation_table[DIK_RSHIFT] = 0; kb_translation_table[DIK_RSHIFT] |= 0xe5 << 8; kb_translation_table[DIK_RWIN] = 0; kb_translation_table[DIK_RWIN] |= 0xe7 << 8; kb_translation_table[DIK_SCROLL] = 0; kb_translation_table[DIK_SCROLL] |= 0x47 << 8; kb_translation_table[DIK_SEMICOLON] = ';'; kb_translation_table[DIK_SEMICOLON] |= 0x33 << 8; kb_translation_table[DIK_SLASH] = '/'; kb_translation_table[DIK_SLASH] |= 0x38 << 8; kb_translation_table[DIK_SPACE] = ' '; kb_translation_table[DIK_SPACE] |= 0x2c << 8; kb_translation_table[DIK_STOP] = 0; kb_translation_table[DIK_STOP] |= 0x78 << 8; kb_translation_table[DIK_SUBTRACT] = '-'; kb_translation_table[DIK_SUBTRACT] |= 0x56 << 8; kb_translation_table[DIK_SYSRQ] = 0; kb_translation_table[DIK_SYSRQ] |= 0x46 << 8; kb_translation_table[DIK_TAB] = '\t'; kb_translation_table[DIK_TAB] |= 0x2b << 8; kb_translation_table[DIK_UP] = 0; kb_translation_table[DIK_UP] |= 0x52 << 8; // kb_translation_table[DIK_VOLUMEDOWN] = 0; // kb_translation_table[DIK_VOLUMEDOWN] |= 0x81; // kb_translation_table[DIK_VOLUMEUP] = 0; // kb_translation_table[DIK_VOLUMEUP] |= 0x80; } static void Keyboard_dikey_to_ascii_and_usb( unsigned char dikey, long & ascii, long & usb ) { unsigned short tr = kb_translation_table[dikey]; ascii = tr & 0xff; usb = ( tr >> 8 ) & 0xff; } static BOOL CALLBACK DIEnumKeyboardProc( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) { GUID guid = lpddi->guidInstance; win32_keyboard * keyboard = new win32_keyboard; EM_log( CK_LOG_INFO, "found %s", lpddi->tszProductName ); strncpy( keyboard->name, lpddi->tszProductName, MAX_PATH ); if( lpdi->CreateDevice( guid, ( LPDIRECTINPUTDEVICE * ) &keyboard->lpdiKeyboard, NULL ) != DI_OK ) { delete keyboard; EM_log( CK_LOG_WARNING, "error: unable to initialize device %s", lpddi->tszProductName ); return DIENUM_CONTINUE; } keyboards->push_back( keyboard ); return DIENUM_CONTINUE; } void Keyboard_init() { if( keyboards != NULL ) return; EM_log( CK_LOG_INFO, "initializing keyboard" ); EM_pushlog(); HINSTANCE hInstance = GetModuleHandle( NULL ); if( lpdi == NULL ) { if( DirectInputCreate( hInstance, DIRECTINPUT_VERSION, &lpdi, NULL) != DI_OK ) { lpdi = NULL; EM_log( CK_LOG_SEVERE, "error: unable to initialize DirectInput, initialization failed" ); EM_poplog(); return; } } keyboards = new vector< win32_keyboard * >; if( lpdi->EnumDevices( DIDEVTYPE_KEYBOARD, DIEnumKeyboardProc, NULL, DIEDFL_ATTACHEDONLY ) != DI_OK ) { delete keyboards; keyboards = NULL; lpdi->Release(); lpdi = NULL; EM_log( CK_LOG_SEVERE, "error: unable to enumerate devices, initialization failed" ); EM_poplog(); return; } Keyboard_init_translation_table(); EM_poplog(); } void Keyboard_poll() { if( !keyboards ) return; win32_keyboard * keyboard; HidMsg msg; vector< win32_keyboard * >::size_type i, len = keyboards->size(); for( i = 0; i < len; i++ ) { keyboard = keyboards->at( i ); if( keyboard->refcount ) { // TODO: convert this to buffered input, or maybe notifications char state[DINPUT_KEYBUFFER_SIZE]; keyboard->lpdiKeyboard->Poll(); if( keyboard->lpdiKeyboard->GetDeviceState( DINPUT_KEYBUFFER_SIZE, state ) != DI_OK ) { EM_log( CK_LOG_WARNING, "keyboard: GetDeviceState failed for %s", keyboard->name ); continue; } for( int j = 0; j < DINPUT_KEYBUFFER_SIZE; j++ ) { if( ( state[j] & 0x80 ) ^ ( keyboard->last_state[j] & 0x80 ) ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_KEYBOARD; msg.type = ( state[j] & 0x80 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = j; msg.idata[0] = ( state[j] & 0x80 ) ? 1 : 0; Keyboard_dikey_to_ascii_and_usb( j, msg.idata[2], msg.idata[1] ); HidInManager::push_message( msg ); } } memcpy( keyboard->last_state, state, DINPUT_KEYBUFFER_SIZE ); } else if( keyboard->needs_close ) { keyboard->needs_close = FALSE; keyboard->lpdiKeyboard->Unacquire(); keyboard->lpdiKeyboard->SetEventNotification( NULL ); } } } void Keyboard_quit() { if( keyboards ) { win32_keyboard * keyboard; vector< win32_keyboard * >::size_type i, len = keyboards->size(); for( i = 0; i < len; i++ ) { keyboard = keyboards->at( i ); if( keyboard->refcount > 0 || keyboard->needs_close) { keyboard->needs_close = FALSE; keyboard->refcount = 0; keyboard->lpdiKeyboard->Unacquire(); keyboard->lpdiKeyboard->SetEventNotification( NULL ); } keyboard->lpdiKeyboard->Release(); delete keyboard; } delete keyboards; keyboards = NULL; } if( lpdi ) { lpdi->Release(); lpdi = NULL; } } int Keyboard_count() { if( !keyboards ) return 0; return keyboards->size(); } int Keyboard_open( int k ) { if( !keyboards || k < 0 || k >= keyboards->size() ) return -1; win32_keyboard * keyboard = keyboards->at( k ); if( keyboard->refcount == 0 ) { if( keyboard->lpdiKeyboard->SetDataFormat( &c_dfDIKeyboard ) != DI_OK ) { return -1; } if( keyboard->lpdiKeyboard->SetEventNotification( g_device_event ) != DI_OK ) { // fallback to sleep+poll mode g_wait_function = Hid_wait_usleep; SetEvent( g_device_event ); } if( keyboard->lpdiKeyboard->Acquire() != DI_OK ) { keyboard->lpdiKeyboard->SetEventNotification( NULL ); return -1; } } keyboard->refcount++; return 0; } int Keyboard_close( int k ) { if( !keyboards || k < 0 || k >= keyboards->size() ) return -1; win32_keyboard * keyboard = keyboards->at( k ); keyboard->refcount--; if( keyboard->refcount < 1 ) keyboard->needs_close = TRUE; return 0; } const char * Keyboard_name( int kb ) { if( !keyboards || kb < 0 || kb >= keyboards->size() ) return NULL; return keyboards->at( kb )->name; } /***************************************************************************** Windows mouse support *****************************************************************************/ #pragma mark Windows mouse support struct win32_mouse { win32_mouse() { refcount = 0; needs_close = FALSE; lpdiMouse = NULL; memset( &last_state, 0, sizeof( last_state ) ); } LPDIRECTINPUTDEVICE2 lpdiMouse; DIMOUSESTATE last_state; char name[MAX_PATH]; t_CKUINT refcount; t_CKBOOL needs_close; }; static vector< win32_mouse * > * mice; static BOOL CALLBACK DIEnumMouseProc( LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef ) { GUID guid = lpddi->guidInstance; win32_mouse * mouse = new win32_mouse; EM_log( CK_LOG_INFO, "found %s", lpddi->tszProductName ); strncpy( mouse->name, lpddi->tszProductName, MAX_PATH ); if( lpdi->CreateDevice( guid, ( LPDIRECTINPUTDEVICE * ) &mouse->lpdiMouse, NULL ) != DI_OK ) { delete mouse; return DIENUM_CONTINUE; } mice->push_back( mouse ); return DIENUM_CONTINUE; } void Mouse_init() { if( mice != NULL ) return; EM_log( CK_LOG_INFO, "initializing mouse" ); EM_pushlog(); HINSTANCE hInstance = GetModuleHandle( NULL ); if( lpdi == NULL ) { if( DirectInputCreate( hInstance, DIRECTINPUT_VERSION, &lpdi, NULL) != DI_OK ) { lpdi = NULL; EM_poplog(); return; } } mice = new vector< win32_mouse * >; if( lpdi->EnumDevices( DIDEVTYPE_MOUSE, DIEnumMouseProc, NULL, DIEDFL_ATTACHEDONLY ) != DI_OK ) { delete mice; mice = NULL; lpdi->Release(); lpdi = NULL; EM_poplog(); return; } EM_poplog(); } void Mouse_poll() { if( !mice ) return; win32_mouse * mouse; HidMsg msg; vector< win32_mouse * >::size_type i, len = mice->size(); for( i = 0; i < len; i++ ) { mouse = mice->at( i ); if( mouse->refcount ) { // TODO: convert this to buffered input, or maybe notifications DIMOUSESTATE state; mouse->lpdiMouse->Poll(); if( mouse->lpdiMouse->GetDeviceState( sizeof( DIMOUSESTATE ), &state ) != DI_OK ) { EM_log( CK_LOG_WARNING, "mouse: GetDeviceState failed for %s", mouse->name ); continue; } if( state.lX != 0 || state.lY != 0 ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_MOUSE; msg.type = CK_HID_MOUSE_MOTION; msg.eid = 0; msg.idata[0] = state.lX; msg.idata[1] = state.lY; HidInManager::push_message( msg ); } if( state.lZ != 0 ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_MOUSE; msg.type = CK_HID_MOUSE_WHEEL; msg.eid = 0; msg.idata[0] = 0; msg.idata[1] = state.lZ; HidInManager::push_message( msg ); } for( int j = 0; j < 4; j++ ) { if( ( state.rgbButtons[j] & 0x80 ) ^ ( mouse->last_state.rgbButtons[j] & 0x80 ) ) { msg.clear(); msg.device_num = i; msg.device_type = CK_HID_DEV_MOUSE; msg.type = ( state.rgbButtons[j] & 0x80 ) ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = j; msg.idata[0] = ( state.rgbButtons[j] & 0x80 ) ? 1 : 0; HidInManager::push_message( msg ); } } mouse->last_state = state; } else if( mouse->needs_close ) { mouse->needs_close = FALSE; mouse->lpdiMouse->Unacquire(); mouse->lpdiMouse->SetEventNotification( NULL ); } } } void Mouse_quit() { if( mice ) { win32_mouse * mouse; vector< win32_mouse * >::size_type i, len = mice->size(); for( i = 0; i < len; i++ ) { mouse = mice->at( i ); if( mouse->refcount > 0 || mouse->needs_close) { mouse->needs_close = FALSE; mouse->refcount = 0; mouse->lpdiMouse->Unacquire(); mouse->lpdiMouse->SetEventNotification( NULL ); } mouse->lpdiMouse->Release(); delete mouse; } delete mice; mice = NULL; } if( lpdi ) { lpdi->Release(); lpdi = NULL; } } int Mouse_count() { if( !mice ) return 0; return mice->size(); } int Mouse_open( int m ) { if( !mice || m < 0 || m >= mice->size() ) return -1; win32_mouse * mouse = mice->at( m ); if( mouse->refcount == 0 ) { if( mouse->lpdiMouse->SetDataFormat( &c_dfDIMouse ) != DI_OK ) { return -1; } if( mouse->lpdiMouse->SetEventNotification( g_device_event ) != DI_OK ) { // fallback to sleep+poll mode g_wait_function = Hid_wait_usleep; SetEvent( g_device_event ); } if( mouse->lpdiMouse->Acquire() != DI_OK ) { mouse->lpdiMouse->SetEventNotification( g_device_event ); return -1; } } mouse->refcount++; return 0; } int Mouse_close( int m ) { if( !mice || m < 0 || m >= mice->size() ) return -1; win32_mouse * mouse = mice->at( m ); mouse->refcount--; if( mouse->refcount < 1 ) mouse->needs_close = TRUE; // let the polling thread take care of it return 0; } const char * Mouse_name( int m ) { if( !mice || m < 0 || m >= mice->size() ) return NULL; return mice->at( m )->name; } #elif defined( __PLATFORM_WIN32__ ) || defined( __WINDOWS_PTHREAD__ ) && defined( USE_RAWINPUT ) void Joystick_init() { } void Joystick_poll() { } void Joystick_quit() { } int Joystick_count() { return 0; } int Joystick_open( int js ) { return -1; } int Joystick_close( int js ) { return -1; } void Mouse_init() { } void Mouse_poll() { } void Mouse_quit() { } int Mouse_count() { return 0; } int Mouse_open( int js ) { return -1; } int Mouse_close( int js ) { return -1; } void Keyboard_init() { } void Keyboard_poll() { } void Keyboard_quit() { } int Keyboard_count() { return 0; } int Keyboard_open( int js ) { return -1; } int Keyboard_close( int js ) { return -1; } #elif defined( __LINUX_ALSA__ ) || defined( __LINUX_OSS__ ) || defined( __LINUX_JACK__ ) /***************************************************************************** Linux general HID support *****************************************************************************/ #pragma mark Linux general HID support #include #include #include #include #include #include #include #include #include #include #include #include #define CK_HID_DIR ("/dev/input") #define CK_HID_MOUSEFILE ("mouse%d") #define CK_HID_JOYSTICKFILE ("js%d") #define CK_HID_EVDEVFILE ("event%d") #define CK_HID_STRBUFSIZE (1024) #define CK_HID_NAMESIZE (128) class linux_device { public: linux_device() { fd = -1; num = -1; refcount = 0; pollfds_i = 0; filename[0] = '\0'; needs_open = needs_close = FALSE; strncpy( name, "(name unknown)", CK_HID_NAMESIZE ); } virtual void callback() = 0; int fd; // file descriptor t_CKINT num; // index in the respective device vector {joysticks, mice, keyboards} t_CKUINT refcount; size_t pollfds_i; t_CKBOOL needs_open; t_CKBOOL needs_close; char filename[CK_HID_STRBUFSIZE]; char name[CK_HID_NAMESIZE]; }; class linux_joystick : public linux_device { public: linux_joystick() : linux_device() { js_num = -1; } virtual void callback() { js_event event; HidMsg msg; ssize_t len; while( ( len = read( fd, &event, sizeof( event ) ) ) > 0 ) { if( len < sizeof( event ) ) { EM_log( CK_LOG_WARNING, "joystick: read event from %s smaller than expected, ignoring", name ); continue; } if( event.type == JS_EVENT_INIT ) continue; msg.device_type = CK_HID_DEV_JOYSTICK; msg.device_num = num; msg.eid = event.number; switch( event.type ) { case JS_EVENT_BUTTON: msg.type = event.value ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = event.value; break; case JS_EVENT_AXIS: msg.type = CK_HID_JOYSTICK_AXIS; msg.fdata[0] = ((t_CKFLOAT)event.value) / ((t_CKFLOAT) SHRT_MAX); break; default: EM_log( CK_LOG_WARNING, "joystick: unknown event type from %s, ignoring", name ); continue; } HidInManager::push_message( msg ); } } int js_num; // /dev/input/js# <-- the # }; #define __LITTLE_ENDIAN__ struct ps2_mouse_event { #ifdef __BIG_ENDIAN__ unsigned unused:2; unsigned y_reverse_motion:1; unsigned x_reverse_motion:1; unsigned always1:1; unsigned button3:1; unsigned button2:1; unsigned button1:1; signed dx:8; signed dy:8; #elif defined( __LITTLE_ENDIAN__ ) unsigned button1:1; unsigned button2:1; unsigned button3:1; unsigned always1:1; unsigned x_reverse_motion:1; unsigned y_reverse_motion:1; unsigned unused:2; signed dx:8; signed dy:8; #else #error unknown endian mode (both __LITTLE_ENDIAN__ and __BIG_ENDIAN__ undefined) #endif } __attribute__ ((__packed__)); class linux_mouse : public linux_device { public: linux_mouse() : linux_device() { m_num = -1; memset( &last_event, 0, sizeof( last_event ) ); } virtual void callback() { //ps2_mouse_event event; input_event event; HidMsg msg; ssize_t len; while( ( len = read( fd, &event, sizeof( event ) ) ) > 0 ) { if( len < sizeof( event ) ) { EM_log( CK_LOG_WARNING, "mouse: read event from mouse %i smaller than expected (%i), ignoring", num, len ); continue; } switch( event.type ) { case EV_KEY: if( event.code & BTN_MOUSE ) { msg.clear(); msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; msg.eid = event.code - BTN_MOUSE; msg.type = event.value ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = event.value; HidInManager::push_message( msg ); } break; case EV_REL: msg.clear(); msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; switch( event.code ) { case REL_X: msg.type = CK_HID_MOUSE_MOTION; msg.idata[0] = event.value; msg.idata[1] = 0; break; case REL_Y: msg.type = CK_HID_MOUSE_MOTION; msg.idata[0] = 0; msg.idata[1] = event.value; break; case REL_HWHEEL: msg.type = CK_HID_MOUSE_WHEEL; msg.idata[0] = event.value; msg.idata[1] = 0; break; case REL_Z: case REL_WHEEL: msg.type = CK_HID_MOUSE_WHEEL; msg.idata[0] = 0; msg.idata[1] = event.value; break; } HidInManager::push_message( msg ); break; } /* if( event.dx || event.dy ) { msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; msg.eid = 0; msg.type = CK_HID_MOUSE_MOTION; msg.idata[0] = event.dx; msg.idata[1] = event.dy; HidInManager::push_message( msg ); } if( event.button1 ^ last_event.button1 ) { msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; msg.eid = 0; msg.type = event.button1 ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = event.button1; HidInManager::push_message( msg ); } if( event.button2 ^ last_event.button2 ) { msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; msg.eid = 2; msg.type = event.button2 ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = event.button2; HidInManager::push_message( msg ); } if( event.button3 ^ last_event.button3 ) { msg.device_type = CK_HID_DEV_MOUSE; msg.device_num = num; msg.eid = 3; msg.type = event.button3 ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.idata[0] = event.button3; HidInManager::push_message( msg ); } */ memcpy( &last_event, &event, sizeof( last_event ) ); } } int m_num; // /dev/input/mouse# <-- the # //ps2_mouse_event last_event; input_event last_event; }; static unsigned short kb_translation_table[KEY_UNKNOWN]; static void Keyboard_init_translation_table() { memset( kb_translation_table, 0, sizeof( kb_translation_table ) ); kb_translation_table[KEY_ESC] = '\e'; kb_translation_table[KEY_ESC] |= 0x29 << 8; kb_translation_table[KEY_1] = '1'; kb_translation_table[KEY_1] |= 0x1e << 8; kb_translation_table[KEY_2] = '2'; kb_translation_table[KEY_2] |= 0x1f << 8; kb_translation_table[KEY_3] = '3'; kb_translation_table[KEY_3] |= 0x20 << 8; kb_translation_table[KEY_4] = '4'; kb_translation_table[KEY_4] |= 0x21 << 8; kb_translation_table[KEY_5] = '5'; kb_translation_table[KEY_5] |= 0x22 << 8; kb_translation_table[KEY_6] = '6'; kb_translation_table[KEY_6] |= 0x23 << 8; kb_translation_table[KEY_7] = '7'; kb_translation_table[KEY_7] |= 0x24 << 8; kb_translation_table[KEY_8] = '8'; kb_translation_table[KEY_8] |= 0x25 << 8; kb_translation_table[KEY_9] = '9'; kb_translation_table[KEY_9] |= 0x26 << 8; kb_translation_table[KEY_0] = '0'; kb_translation_table[KEY_0] |= 0x27 << 8; kb_translation_table[KEY_MINUS] = '-'; kb_translation_table[KEY_MINUS] |= 0x2d << 8; kb_translation_table[KEY_EQUAL] = '='; kb_translation_table[KEY_EQUAL] |= 0x2e << 8; kb_translation_table[KEY_BACKSPACE] = '\b'; kb_translation_table[KEY_BACKSPACE] |= 0x2a << 8; kb_translation_table[KEY_TAB] = '\t'; kb_translation_table[KEY_TAB] |= 0x2b << 8; kb_translation_table[KEY_Q] = 'Q'; kb_translation_table[KEY_Q] |= 0x14 << 8; kb_translation_table[KEY_W] = 'W'; kb_translation_table[KEY_W] |= 0x1a << 8; kb_translation_table[KEY_E] = 'E'; kb_translation_table[KEY_E] |= 0x08 << 8; kb_translation_table[KEY_R] = 'R'; kb_translation_table[KEY_R] |= 0x15 << 8; kb_translation_table[KEY_T] = 'T'; kb_translation_table[KEY_T] |= 0x17 << 8; kb_translation_table[KEY_Y] = 'Y'; kb_translation_table[KEY_Y] |= 0x1c << 8; kb_translation_table[KEY_U] = 'U'; kb_translation_table[KEY_U] |= 0x18 << 8; kb_translation_table[KEY_I] = 'I'; kb_translation_table[KEY_I] |= 0x0c << 8; kb_translation_table[KEY_O] = 'O'; kb_translation_table[KEY_O] |= 0x12 << 8; kb_translation_table[KEY_P] = 'P'; kb_translation_table[KEY_P] |= 0x13 << 8; kb_translation_table[KEY_LEFTBRACE] = '['; kb_translation_table[KEY_LEFTBRACE] |= 0x2f << 8; kb_translation_table[KEY_RIGHTBRACE] = ']'; kb_translation_table[KEY_RIGHTBRACE] |= 0x30 << 8; kb_translation_table[KEY_ENTER] = '\n'; kb_translation_table[KEY_ENTER] |= 0x28 << 8; kb_translation_table[KEY_LEFTCTRL] = 0; kb_translation_table[KEY_LEFTCTRL] |= 0xe0 << 8; kb_translation_table[KEY_A] = 'A'; kb_translation_table[KEY_A] |= 0x04 << 8; kb_translation_table[KEY_S] = 'S'; kb_translation_table[KEY_S] |= 0x22 << 8; kb_translation_table[KEY_D] = 'D'; kb_translation_table[KEY_D] |= 0x07 << 8; kb_translation_table[KEY_F] = 'F'; kb_translation_table[KEY_F] |= 0x09 << 8; kb_translation_table[KEY_G] = 'G'; kb_translation_table[KEY_G] |= 0x0a << 8; kb_translation_table[KEY_H] = 'H'; kb_translation_table[KEY_H] |= 0x0b << 8; kb_translation_table[KEY_J] = 'J'; kb_translation_table[KEY_J] |= 0x0d << 8; kb_translation_table[KEY_K] = 'K'; kb_translation_table[KEY_K] |= 0x0e << 8; kb_translation_table[KEY_L] = 'L'; kb_translation_table[KEY_L] |= 0x0f << 8; kb_translation_table[KEY_SEMICOLON] = ';'; kb_translation_table[KEY_SEMICOLON] |= 0x33 << 8; kb_translation_table[KEY_APOSTROPHE] = '\''; kb_translation_table[KEY_APOSTROPHE] |= 0x34 << 8; kb_translation_table[KEY_GRAVE] = '`'; kb_translation_table[KEY_GRAVE] |= 0x35 << 8; kb_translation_table[KEY_LEFTSHIFT] = 0; kb_translation_table[KEY_LEFTSHIFT] |= 0xe1 << 8; kb_translation_table[KEY_BACKSLASH] = '\\'; kb_translation_table[KEY_BACKSLASH] |= 0x31 << 8; kb_translation_table[KEY_Z] = 'Z'; kb_translation_table[KEY_Z] |= 0x1d << 8; kb_translation_table[KEY_X] = 'X'; kb_translation_table[KEY_X] |= 0x1b << 8; kb_translation_table[KEY_C] = 'C'; kb_translation_table[KEY_C] |= 0x06 << 8; kb_translation_table[KEY_V] = 'V'; kb_translation_table[KEY_V] |= 0x19 << 8; kb_translation_table[KEY_B] = 'B'; kb_translation_table[KEY_B] |= 0x05 << 8; kb_translation_table[KEY_N] = 'N'; kb_translation_table[KEY_N] |= 0x11 << 8; kb_translation_table[KEY_M] = 'M'; kb_translation_table[KEY_M] |= 0x10 << 8; kb_translation_table[KEY_COMMA] = ','; kb_translation_table[KEY_COMMA] |= 0x36 << 8; kb_translation_table[KEY_DOT] = '.'; kb_translation_table[KEY_DOT] |= 0x37 << 8; kb_translation_table[KEY_SLASH] = '/'; kb_translation_table[KEY_SLASH] |= 0x38 << 8; kb_translation_table[KEY_RIGHTSHIFT] = 0; kb_translation_table[KEY_RIGHTSHIFT] |= 0xe5 << 8; kb_translation_table[KEY_KPASTERISK] = '*'; kb_translation_table[KEY_KPASTERISK] |= 0x55 << 8; kb_translation_table[KEY_LEFTALT] = 0; kb_translation_table[KEY_LEFTALT] |= 0xe2 << 8; kb_translation_table[KEY_SPACE] = ' '; kb_translation_table[KEY_SPACE] |= 0x2c << 8; kb_translation_table[KEY_CAPSLOCK] = 0; kb_translation_table[KEY_CAPSLOCK] |= 0x39 << 8; kb_translation_table[KEY_F1] = 0; kb_translation_table[KEY_F1] |= 0x3a << 8; kb_translation_table[KEY_F2] = 0; kb_translation_table[KEY_F2] |= 0x3b << 8; kb_translation_table[KEY_F3] = 0; kb_translation_table[KEY_F3] |= 0x3c << 8; kb_translation_table[KEY_F4] = 0; kb_translation_table[KEY_F4] |= 0x3d << 8; kb_translation_table[KEY_F5] = 0; kb_translation_table[KEY_F5] |= 0x3e << 8; kb_translation_table[KEY_F6] = 0; kb_translation_table[KEY_F6] |= 0x3f << 8; kb_translation_table[KEY_F7] = 0; kb_translation_table[KEY_F7] |= 0x40 << 8; kb_translation_table[KEY_F8] = 0; kb_translation_table[KEY_F8] |= 0x41 << 8; kb_translation_table[KEY_F9] = 0; kb_translation_table[KEY_F9] |= 0x42 << 8; kb_translation_table[KEY_F10] = 0; kb_translation_table[KEY_F10] |= 0x43 << 8; kb_translation_table[KEY_NUMLOCK] = 0; kb_translation_table[KEY_NUMLOCK] |= 0x53 << 8; kb_translation_table[KEY_SCROLLLOCK] = 0; kb_translation_table[KEY_SCROLLLOCK] |= 0x47 << 8; kb_translation_table[KEY_KP7] = '7'; kb_translation_table[KEY_KP7] |= 0x5f << 8; kb_translation_table[KEY_KP8] = '8'; kb_translation_table[KEY_KP8] |= 0x60 << 8; kb_translation_table[KEY_KP9] = '9'; kb_translation_table[KEY_KP9] |= 0x61 << 8; kb_translation_table[KEY_KPMINUS] = '-'; kb_translation_table[KEY_KPMINUS] |= 0x56 << 8; kb_translation_table[KEY_KP4] = '4'; kb_translation_table[KEY_KP4] |= 0x5c << 8; kb_translation_table[KEY_KP5] = '5'; kb_translation_table[KEY_KP5] |= 0x5d << 8; kb_translation_table[KEY_KP6] = '6'; kb_translation_table[KEY_KP6] |= 0x5e << 8; kb_translation_table[KEY_KPPLUS] = '+'; kb_translation_table[KEY_KPPLUS] |= 0x57 << 8; kb_translation_table[KEY_KP1] = '1'; kb_translation_table[KEY_KP1] |= 0x59 << 8; kb_translation_table[KEY_KP2] = '2'; kb_translation_table[KEY_KP2] |= 0x51 << 8; kb_translation_table[KEY_KP3] = '3'; kb_translation_table[KEY_KP3] |= 0x52 << 8; kb_translation_table[KEY_KP0] = '0'; kb_translation_table[KEY_KP0] |= 0x62 << 8; kb_translation_table[KEY_KPDOT] = '.'; kb_translation_table[KEY_KPDOT] |= 0x63 << 8; kb_translation_table[KEY_F11] = 0; kb_translation_table[KEY_F11] |= 0x44 << 8; kb_translation_table[KEY_F12] = 0; kb_translation_table[KEY_F12] |= 0x45 << 8; // kb_translation_table[KEY_KPJPCOMMA] = ','; // kb_translation_table[KEY_KPJPCOMMA] |= 0x85 << 8; kb_translation_table[KEY_KPENTER] = '\n'; kb_translation_table[KEY_KPENTER] |= 0x58 << 8; kb_translation_table[KEY_RIGHTCTRL] = 0; kb_translation_table[KEY_RIGHTCTRL] |= 0xe4 << 8; kb_translation_table[KEY_KPSLASH] = '/'; kb_translation_table[KEY_KPSLASH] |= 0x54 << 8; kb_translation_table[KEY_SYSRQ] = 0; kb_translation_table[KEY_SYSRQ] |= 0x46 << 8; kb_translation_table[KEY_RIGHTALT] = 0; kb_translation_table[KEY_RIGHTALT] |= 0xe6 << 8; kb_translation_table[KEY_HOME] = 0; kb_translation_table[KEY_HOME] |= 0x4a << 8; kb_translation_table[KEY_UP] = 0; kb_translation_table[KEY_UP] |= 0x52 << 8; kb_translation_table[KEY_PAGEUP] = 0; kb_translation_table[KEY_PAGEUP] |= 0x4b << 8; kb_translation_table[KEY_LEFT] = 0; kb_translation_table[KEY_LEFT] |= 0x50 << 8; kb_translation_table[KEY_RIGHT] = 0; kb_translation_table[KEY_RIGHT] |= 0x4f << 8; kb_translation_table[KEY_END] = 0; kb_translation_table[KEY_END] |= 0x4d << 8; kb_translation_table[KEY_DOWN] = 0; kb_translation_table[KEY_DOWN] |= 0x51 << 8; kb_translation_table[KEY_PAGEDOWN] = 0; kb_translation_table[KEY_PAGEDOWN] |= 0x4e << 8; kb_translation_table[KEY_INSERT] = 0; kb_translation_table[KEY_INSERT] |= 0x49 << 8; kb_translation_table[KEY_DELETE] = 0x7f; kb_translation_table[KEY_DELETE] |= 0x4c << 8; kb_translation_table[KEY_MUTE] = 0; kb_translation_table[KEY_MUTE] |= 0x7f << 8; kb_translation_table[KEY_VOLUMEDOWN] = 0; kb_translation_table[KEY_VOLUMEDOWN] |= 0x81 << 8; kb_translation_table[KEY_VOLUMEUP] = 0; kb_translation_table[KEY_VOLUMEUP] |= 0x80 << 8; kb_translation_table[KEY_POWER] = 0; kb_translation_table[KEY_POWER] |= 0x66 << 8; kb_translation_table[KEY_KPEQUAL] = '='; kb_translation_table[KEY_KPEQUAL] |= 0x67 << 8; kb_translation_table[KEY_PAUSE] = 0; kb_translation_table[KEY_PAUSE] |= 0x48 << 8; kb_translation_table[KEY_KPCOMMA] = ','; kb_translation_table[KEY_KPCOMMA] |= 0x85 << 8; kb_translation_table[KEY_LEFTMETA] = 0; kb_translation_table[KEY_LEFTMETA] |= 0xe3 << 8; kb_translation_table[KEY_RIGHTMETA] = 0; kb_translation_table[KEY_RIGHTMETA] |= 0xe7 << 8; kb_translation_table[KEY_STOP] = 0; kb_translation_table[KEY_STOP] |= 0x78 << 8; kb_translation_table[KEY_AGAIN] = 0; kb_translation_table[KEY_AGAIN] |= 0x79 << 8; kb_translation_table[KEY_UNDO] = 0; kb_translation_table[KEY_UNDO] |= 0x7a << 8; kb_translation_table[KEY_COPY] = 0; kb_translation_table[KEY_COPY] |= 0x7c << 8; kb_translation_table[KEY_PASTE] = 0; kb_translation_table[KEY_PASTE] |= 0x7d << 8; kb_translation_table[KEY_FIND] = 0; kb_translation_table[KEY_FIND] |= 0x7e << 8; kb_translation_table[KEY_CUT] = 0; kb_translation_table[KEY_CUT] |= 0x7b << 8; kb_translation_table[KEY_HELP] = 0; kb_translation_table[KEY_HELP] |= 0x75 << 8; kb_translation_table[KEY_MENU] = 0; kb_translation_table[KEY_MENU] |= 0x76 << 8; kb_translation_table[KEY_F13] = 0; kb_translation_table[KEY_F13] |= 0x68 << 8; kb_translation_table[KEY_F14] = 0; kb_translation_table[KEY_F14] |= 0x69 << 8; kb_translation_table[KEY_F15] = 0; kb_translation_table[KEY_F15] |= 0x6a << 8; kb_translation_table[KEY_F16] = 0; kb_translation_table[KEY_F16] |= 0x6b << 8; kb_translation_table[KEY_F17] = 0; kb_translation_table[KEY_F17] |= 0x6c << 8; kb_translation_table[KEY_F18] = 0; kb_translation_table[KEY_F18] |= 0x6d << 8; kb_translation_table[KEY_F19] = 0; kb_translation_table[KEY_F19] |= 0x6e << 8; kb_translation_table[KEY_F20] = 0; kb_translation_table[KEY_F20] |= 0x6f << 8; kb_translation_table[KEY_F21] = 0; kb_translation_table[KEY_F21] |= 0x70 << 8; kb_translation_table[KEY_F22] = 0; kb_translation_table[KEY_F22] |= 0x71 << 8; kb_translation_table[KEY_F23] = 0; kb_translation_table[KEY_F23] |= 0x72 << 8; kb_translation_table[KEY_F24] = 0; kb_translation_table[KEY_F24] |= 0x73 << 8; } static void Keyboard_translate_key( __u16 evdev_key, long & ascii, long & usb ) { unsigned short tr = kb_translation_table[evdev_key]; ascii = tr & 0xff; usb = ( tr >> 8 ) & 0xff; } class linux_keyboard : public linux_device { public: linux_keyboard() : linux_device() { } virtual void callback() { input_event event; HidMsg msg; ssize_t len; while( ( len = read( fd, &event, sizeof( event ) ) ) > 0 ) { if( len < sizeof( event ) ) { EM_log( CK_LOG_WARNING, "keyboard: read event from keyboard %i smaller than expected (%i), ignoring", num, len ); continue; } if( event.type != EV_KEY ) continue; if( event.value == 2 ) continue; msg.clear(); msg.device_type = CK_HID_DEV_KEYBOARD; msg.device_num = num; msg.type = event.value ? CK_HID_BUTTON_DOWN : CK_HID_BUTTON_UP; msg.eid = event.code; msg.idata[0] = event.value; Keyboard_translate_key( event.code, msg.idata[2], msg.idata[1] ); HidInManager::push_message( msg ); } } }; static vector< linux_joystick * > * joysticks = NULL; static vector< linux_mouse * > * mice = NULL; static vector< linux_keyboard * > * keyboards = NULL; static map< int, linux_device * > * device_map = NULL; static pollfd * pollfds = NULL; #define DEFAULT_POLLFDS_SIZE (1) static size_t pollfds_size = 0; static size_t pollfds_end = 0; static int hid_channel_r = -1; // HID communications channel, read fd static int hid_channel_w = -1; // HID communications channel, write fd struct hid_channel_msg { int action; #define HID_CHANNEL_OPEN 1 #define HID_CHANNEL_CLOSE 0 #define HID_CHANNEL_QUIT -1 linux_device * device; }; static t_CKBOOL g_hid_init = FALSE; void Hid_init() { if( g_hid_init ) return; pollfds = new pollfd[DEFAULT_POLLFDS_SIZE]; pollfds_size = DEFAULT_POLLFDS_SIZE; pollfds_end = 0; int filedes[2]; if( pipe( filedes ) ) { EM_log( CK_LOG_SEVERE, "hid: unable to create pipe, initialization failed" ); return; } hid_channel_r = filedes[0]; hid_channel_w = filedes[1]; int fd_flags = fcntl( hid_channel_r, F_GETFL ); fcntl( hid_channel_r, F_SETFL, fd_flags | O_NONBLOCK ); /* right now, the hid_channel is just used as a dummy file descriptor passed to poll, such that poll will work/block even when there are no open devices. In the future hid_channel could also be used to communicate between the VM thread and the HID thread */ pollfds[0].fd = hid_channel_r; pollfds[0].events = POLLIN; pollfds[0].revents = 0; pollfds_end = 1; device_map = new map< int, linux_device * >; Keyboard_init_translation_table(); g_hid_init = TRUE; } void Hid_poll() { if( !g_hid_init ) return; hid_channel_msg hcm; while( poll( pollfds, pollfds_end, -1 ) > 0 ) { for( int i = 1; i < pollfds_end; i++ ) { if( pollfds[i].revents & POLLIN ) { ( *device_map )[pollfds[i].fd]->callback(); pollfds[i].revents = 0; } } if( pollfds[0].revents & POLLIN ) { while( read( hid_channel_r, &hcm, sizeof( hcm ) ) > 0 ) { if( hcm.action == HID_CHANNEL_OPEN ) { if( pollfds_end >= pollfds_size ) { pollfds_size = pollfds_end * 2; pollfd * t_pollfds = new pollfd[pollfds_size]; memcpy( t_pollfds, pollfds, pollfds_end * sizeof( pollfd ) ); delete[] pollfds; pollfds = t_pollfds; } pollfds[pollfds_end].fd = hcm.device->fd; pollfds[pollfds_end].events = POLLIN; pollfds[pollfds_end].revents = 0; hcm.device->pollfds_i = pollfds_end; ( *device_map )[hcm.device->fd] = hcm.device; pollfds_end++; } else if( hcm.action == HID_CHANNEL_CLOSE ) { // erase the closing entry by copying the last entry into it // this is okay even when joystick->pollfds_i == pollfds_end // because we decrement pollfds_end ( *device_map )[pollfds[pollfds_end - 1].fd]->pollfds_i = hcm.device->pollfds_i; pollfds[hcm.device->pollfds_i] = pollfds[pollfds_end - 1]; pollfds_end--; close( hcm.device->fd ); device_map->erase( hcm.device->fd ); } else if( hcm.action == HID_CHANNEL_QUIT ) { close( hid_channel_r ); return; } } break; } } } void Hid_quit() { if( !g_hid_init ) return; hid_channel_msg hcm = { HID_CHANNEL_QUIT, NULL }; write( hid_channel_w, &hcm, sizeof( hcm ) ); close( hid_channel_w ); delete[] pollfds; delete device_map; g_hid_init = FALSE; } int TiltSensor_read( t_CKINT * x, t_CKINT * y, t_CKINT * z ) { return 0; } /***************************************************************************** Linux joystick support *****************************************************************************/ #pragma mark Linux joystick support void Joystick_init() { if( joysticks != NULL ) return; EM_log( CK_LOG_INFO, "initializing joysticks" ); EM_pushlog(); joysticks = new vector< linux_joystick * >; DIR * dir_handle; struct dirent * dir_entity; struct stat stat_buf; int js_num, fd, i; uid_t uid = geteuid(); gid_t gid = getegid(); char buf[CK_HID_STRBUFSIZE]; linux_joystick * js; dir_handle = opendir( CK_HID_DIR ); if( dir_handle == NULL ) { if( errno == EACCES ) EM_log( CK_LOG_WARNING, "hid: error opening %s, unable to initialize joystick", CK_HID_DIR ); EM_poplog(); return; } while( dir_entity = readdir( dir_handle ) ) { if( sscanf( dir_entity->d_name, CK_HID_JOYSTICKFILE, &js_num ) ) { snprintf( buf, CK_HID_STRBUFSIZE, "%s/%s", CK_HID_DIR, dir_entity->d_name ); if( ( fd = open( buf, O_RDONLY | O_NONBLOCK ) ) >= 0 || errno == EACCES ) /* wait to report access errors until the device is actually opened */ { js = new linux_joystick; js->js_num = js_num; js->num = joysticks->size(); if( fd >= 0 ) { ioctl( fd, JSIOCGNAME( CK_HID_NAMESIZE ), js->name ); close( fd ); // no need to keep the file open } strncpy( js->filename, buf, CK_HID_STRBUFSIZE ); joysticks->push_back( js ); EM_log( CK_LOG_INFO, "joystick: found device %s", js->name ); } } } closedir( dir_handle ); EM_poplog(); } void Joystick_poll() { } void Joystick_quit() { if( joysticks == NULL ) return; vector< linux_joystick * >::size_type i, len = joysticks->size(); for( i = 0; i < len; i++ ) delete joysticks->at( i ); delete joysticks; joysticks = NULL; } int Joystick_count() { if( joysticks == NULL ) return 0; return joysticks->size(); } int Joystick_open( int js ) { if( joysticks == NULL || js < 0 || js >= joysticks->size() ) return -1; linux_joystick * joystick = joysticks->at( js ); if( joystick->refcount == 0 ) { if( ( joystick->fd = open( joystick->filename, O_RDONLY | O_NONBLOCK ) ) < 0 ) { EM_log( CK_LOG_SEVERE, "joystick: unable to open %s: %s", joystick->filename, strerror( errno ) ); return -1; } hid_channel_msg hcm = { HID_CHANNEL_OPEN, joystick }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } joystick->refcount++; return 0; } int Joystick_close( int js ) { if( joysticks == NULL || js < 0 || js >= joysticks->size() ) return -1; linux_joystick * joystick = joysticks->at( js ); joystick->refcount--; if( joystick->refcount == 0 ) { hid_channel_msg hcm = { HID_CHANNEL_CLOSE, joystick }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } return 0; } const char * Joystick_name( int js ) { if( joysticks == NULL || js < 0 || js >= joysticks->size() ) return NULL; return joysticks->at( js )->name; } #define test_bit( array, bit ) (array[bit/8] & (1<<(bit%8))) void Mouse_configure( const char * filename ) { struct stat statbuf; int fd, devmajor, devminor, is_mouse = 0; linux_mouse * mouse; unsigned char relcaps[(REL_MAX / 8) + 1]; unsigned char abscaps[(ABS_MAX / 8) + 1]; unsigned char keycaps[(KEY_MAX / 8) + 1]; if( stat( filename, &statbuf ) == -1 ) return; if( S_ISCHR( statbuf.st_mode ) == 0 ) return; /* not a character device... */ devmajor = ( statbuf.st_rdev & 0xFF00 ) >> 8; devminor = ( statbuf.st_rdev & 0x00FF ); if ( ( devmajor != 13 ) || ( devminor < 64 ) || ( devminor > 96 ) ) return; /* not an evdev. */ if( ( fd = open( filename, O_RDONLY | O_NONBLOCK ) ) < 0 ) return; memset( relcaps, 0, sizeof( relcaps ) ); memset( abscaps, 0, sizeof( abscaps ) ); memset( keycaps, 0, sizeof( keycaps ) ); //int num_keys = 0; if( ioctl( fd, EVIOCGBIT( EV_KEY, sizeof( keycaps ) ), keycaps ) == -1 ) return; is_mouse = 0; if( ioctl( fd, EVIOCGBIT( EV_REL, sizeof( relcaps ) ), relcaps ) != -1 ) { if( test_bit( relcaps, REL_X ) && test_bit( relcaps, REL_Y ) && test_bit( keycaps, BTN_MOUSE ) ) { is_mouse = 1; } if( test_bit( relcaps, REL_DIAL ) ) is_mouse = 1; } if( ioctl( fd, EVIOCGBIT( EV_ABS, sizeof( abscaps ) ), abscaps ) != -1 ) { if( test_bit( abscaps, ABS_X ) && test_bit( abscaps, ABS_Y ) && ( test_bit( keycaps, BTN_MOUSE ) || test_bit( keycaps, BTN_TOUCH ) ) ) is_mouse = 1; } if( !is_mouse ) return; mouse = new linux_mouse; mouse->num = mice->size(); ioctl( fd, EVIOCGNAME( CK_HID_NAMESIZE ), mouse->name ); if( fd >= 0 ) close( fd ); // no need to keep the file open strncpy( mouse->filename, filename, CK_HID_STRBUFSIZE ); mice->push_back( mouse ); EM_log( CK_LOG_INFO, "mouse: found device %s", mouse->name ); } void Mouse_init() { if( mice != NULL ) return; EM_log( CK_LOG_INFO, "initializing mice" ); EM_pushlog(); mice = new vector< linux_mouse * >; DIR * dir_handle; struct dirent * dir_entity; struct stat stat_buf; int m_num, fd, i; char buf[CK_HID_STRBUFSIZE]; linux_mouse * mouse; dir_handle = opendir( CK_HID_DIR ); if( dir_handle == NULL ) { EM_log( CK_LOG_WARNING, "hid: error opening %s, unable to initialize mice", CK_HID_DIR ); EM_poplog(); return; } while( dir_entity = readdir( dir_handle ) ) { if( sscanf( dir_entity->d_name, CK_HID_EVDEVFILE, &m_num ) ) { snprintf( buf, CK_HID_STRBUFSIZE, "%s/%s", CK_HID_DIR, dir_entity->d_name ); Mouse_configure( buf ); /* if( ( fd = open( buf, O_RDONLY | O_NONBLOCK ) ) >= 0 || errno == EACCES ) *//* wait to report access errors until the device is actually opened *//* { mouse = new linux_mouse; mouse->m_num = m_num; mouse->num = mice->size(); //ioctl( fd, JSIOCGNAME( CK_HID_NAMESIZE ), js->name ); if( fd >= 0 ) close( fd ); // no need to keep the file open strncpy( mouse->filename, buf, CK_HID_STRBUFSIZE ); mice->push_back( mouse ); //EM_log( CK_LOG_INFO, "mouse: found device %s", mouse->name ); }*/ } } closedir( dir_handle ); EM_poplog(); } void Mouse_poll() { } void Mouse_quit() { if( mice == NULL ) return; vector< linux_mouse * >::size_type i, len = mice->size(); for( i = 0; i < len; i++ ) delete mice->at( i ); delete mice; mice = NULL; } int Mouse_count() { if( !mice ) return 0; return mice->size(); } int Mouse_open( int m ) { if( mice == NULL || m < 0 || m >= mice->size() ) return -1; linux_mouse * mouse = mice->at( m ); if( mouse->refcount == 0 ) { if( ( mouse->fd = open( mouse->filename, O_RDONLY | O_NONBLOCK ) ) < 0 ) { EM_log( CK_LOG_SEVERE, "mouse: unable to open %s: %s", mouse->filename, strerror( errno ) ); return -1; } mouse->needs_open = TRUE; hid_channel_msg hcm = { HID_CHANNEL_OPEN, mouse }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } mouse->refcount++; return 0; } int Mouse_close( int m ) { if( mice == NULL || m < 0 || m >= mice->size() ) return -1; linux_mouse * mouse = mice->at( m ); mouse->refcount--; if( mouse->refcount == 0 ) { mouse->needs_close = TRUE; hid_channel_msg hcm = { HID_CHANNEL_CLOSE, mouse }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } return 0; } const char * Mouse_name( int m ) { if( mice == NULL || m < 0 || m >= mice->size() ) return NULL; return mice->at( m )->name; } void Keyboard_configure( const char * filename ) { struct stat statbuf; int fd, devmajor, devminor; linux_keyboard * keyboard; unsigned char relcaps[(REL_MAX / 8) + 1]; unsigned char abscaps[(ABS_MAX / 8) + 1]; unsigned char keycaps[(KEY_MAX / 8) + 1]; if( stat( filename, &statbuf ) == -1 ) return; if( S_ISCHR( statbuf.st_mode ) == 0 ) return; /* not a character device... */ devmajor = ( statbuf.st_rdev & 0xFF00 ) >> 8; devminor = ( statbuf.st_rdev & 0x00FF ); if ( ( devmajor != 13 ) || ( devminor < 64 ) || ( devminor > 96 ) ) return; /* not an evdev. */ if( ( fd = open( filename, O_RDONLY | O_NONBLOCK ) ) < 0 ) return; memset( relcaps, 0, sizeof( relcaps ) ); memset( abscaps, 0, sizeof( abscaps ) ); memset( keycaps, 0, sizeof( keycaps ) ); int num_keys = 0; if( ioctl( fd, EVIOCGBIT( EV_KEY, sizeof( keycaps ) ), keycaps ) == -1 ) return; if( ioctl( fd, EVIOCGBIT( EV_REL, sizeof( relcaps ) ), relcaps ) != -1 ) { for( int i = 0; i < sizeof( relcaps ); i++ ) if( relcaps[i] ) return; } if( ioctl( fd, EVIOCGBIT( EV_ABS, sizeof( abscaps ) ), abscaps ) != -1 ) { for( int i = 0; i < sizeof( abscaps ); i++ ) if( abscaps[i] ) return; } for( int i = 0; i < sizeof( keycaps ); i++ ) { for( int j = 0; j < 8; j++ ) { if( keycaps[i] & ( 1 << j ) ) num_keys++; } } keyboard = new linux_keyboard; keyboard->num = keyboards->size(); ioctl( fd, EVIOCGNAME( CK_HID_NAMESIZE ), keyboard->name ); if( fd >= 0 ) close( fd ); // no need to keep the file open strncpy( keyboard->filename, filename, CK_HID_STRBUFSIZE ); keyboards->push_back( keyboard ); EM_log( CK_LOG_INFO, "keyboard: found device %s", keyboard->name ); } void Keyboard_init() { if( keyboards != NULL ) return; EM_log( CK_LOG_INFO, "initializing keyboards" ); EM_pushlog(); keyboards = new vector< linux_keyboard * >; DIR * dir_handle; struct dirent * dir_entity; int m_num; char buf[CK_HID_STRBUFSIZE]; dir_handle = opendir( CK_HID_DIR ); if( dir_handle == NULL ) { if( errno == EACCES ) EM_log( CK_LOG_WARNING, "hid: error opening %s, unable to initialize keyboards", CK_HID_DIR ); EM_poplog(); return; } while( dir_entity = readdir( dir_handle ) ) { if( sscanf( dir_entity->d_name, CK_HID_EVDEVFILE, &m_num ) ) { snprintf( buf, CK_HID_STRBUFSIZE, "%s/%s", CK_HID_DIR, dir_entity->d_name ); Keyboard_configure( buf ); } } closedir( dir_handle ); EM_poplog(); } void Keyboard_poll() { } void Keyboard_quit() { } int Keyboard_count() { if( keyboards == NULL ) return 0; return keyboards->size(); } int Keyboard_open( int k ) { if( keyboards == NULL || k < 0 || k >= keyboards->size() ) return -1; linux_keyboard * keyboard = keyboards->at( k ); if( keyboard->refcount == 0 ) { if( ( keyboard->fd = open( keyboard->filename, O_RDONLY | O_NONBLOCK ) ) < 0 ) { EM_log( CK_LOG_SEVERE, "keyboard: unable to open %s: %s", keyboard->filename, strerror( errno ) ); return -1; } hid_channel_msg hcm = { HID_CHANNEL_OPEN, keyboard }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } keyboard->refcount++; return 0; } int Keyboard_close( int k ) { if( keyboards == NULL || k < 0 || k >= keyboards->size() ) return -1; linux_keyboard * keyboard = keyboards->at( k ); keyboard->refcount--; if( keyboard->refcount == 0 ) { hid_channel_msg hcm = { HID_CHANNEL_CLOSE, keyboard }; write( hid_channel_w, &hcm, sizeof( hcm ) ); } return 0; } const char * Keyboard_name( int k ) { if( keyboards == NULL || k < 0 || k >= keyboards->size() ) return NULL; return keyboards->at( k )->name; } #endif #pragma mark Hid graveyard /***** empty functions for stuff that isn't yet cross platform *****/ #ifndef __PLATFORM_MACOSX__ /*** empty functions for Mac-only stuff ***/ int Mouse_start_cursor_track(){ return -1; } int Mouse_stop_cursor_track(){ return -1; } int Keyboard_send( int k, const HidMsg * msg ){ return -1; } int WiiRemote_send( int k, const HidMsg * msg ){ return -1; } void WiiRemote_init(){} void WiiRemote_poll(){} void WiiRemote_quit(){} void WiiRemote_probe(){} int WiiRemote_count(){ return 0; } int WiiRemote_open( int wr ){ return -1; } int WiiRemote_open( const char * name ){ return -1; } int WiiRemote_close( int wr ){ return -1; } int WiiRemote_send( const HidMsg * msg ){ return -1; } const char * WiiRemote_name( int wr ){ return NULL; } void TiltSensor_init(){} void TiltSensor_quit(){} void TiltSensor_probe(){} int TiltSensor_count(){ return 0; } int TiltSensor_open( int ts ){ return -1; } int TiltSensor_close( int ts ){ return -1; } int TiltSensor_read( int ts, int type, int num, HidMsg * msg ){ return -1; } const char * TiltSensor_name( int ts ){ return NULL; } #endif chuck-1.2.0.8.dfsg/src/util_hid.h0000644000175000017500000001337710600421720015111 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_hid.h // desc: header file for joystick/mouse/keyboard support // // author: Spencer Salazar (ssalazar@cs.princeton.edu) // date: spring 2006 //----------------------------------------------------------------------------- #ifndef __UTIL_HID_H__ #define __UTIL_HID_H__ //----------------------------------------------------------------------------- // definitions //----------------------------------------------------------------------------- struct HidMsg { t_CKINT device_type; // device type t_CKINT device_num; // device number t_CKINT type; // message type t_CKINT eid; // element id t_CKINT idata[4]; // int data t_CKFLOAT fdata[4]; // float data #ifdef __cplusplus HidMsg() { this->clear(); } void clear() { memset( this, 0, sizeof(HidMsg) ); } #endif }; /* device types */ static const t_CKUINT CK_HID_DEV_NONE = 0; static const t_CKUINT CK_HID_DEV_JOYSTICK = 1; static const t_CKUINT CK_HID_DEV_MOUSE = 2; static const t_CKUINT CK_HID_DEV_KEYBOARD = 3; static const t_CKUINT CK_HID_DEV_WIIREMOTE = 4; static const t_CKUINT CK_HID_DEV_TILTSENSOR = 5; static const t_CKUINT CK_HID_DEV_TABLET = 6; static const t_CKUINT CK_HID_DEV_COUNT = 7; /* message types */ static const t_CKUINT CK_HID_JOYSTICK_AXIS = 0; static const t_CKUINT CK_HID_BUTTON_DOWN = 1; static const t_CKUINT CK_HID_BUTTON_UP = 2; static const t_CKUINT CK_HID_JOYSTICK_HAT = 3; static const t_CKUINT CK_HID_JOYSTICK_BALL = 4; static const t_CKUINT CK_HID_MOUSE_MOTION = 5; static const t_CKUINT CK_HID_MOUSE_WHEEL = 6; static const t_CKUINT CK_HID_DEVICE_CONNECTED = 7; static const t_CKUINT CK_HID_DEVICE_DISCONNECTED = 8; static const t_CKUINT CK_HID_ACCELEROMETER = 9; static const t_CKUINT CK_HID_WIIREMOTE_IR = 10; static const t_CKUINT CK_HID_LED = 11; static const t_CKUINT CK_HID_FORCE_FEEDBACK = 12; static const t_CKUINT CK_HID_SPEAKER = 13; static const t_CKUINT CK_HID_TABLET_PRESSURE = 14; static const t_CKUINT CK_HID_TABLET_MOTION = 15; static const t_CKUINT CK_HID_TABLET_ROTATION = 16; static const t_CKUINT CK_HID_MSG_COUNT = 17; /* keys */ /* extension API */ struct _Chuck_Hid_Driver { void ( *init )(); void ( *quit )(); void ( *poll )(); void ( *probe )(); int ( *count )(); int ( *open )( int ); int ( *open_async )( int ); int ( *close )( int ); int ( *send )( int, const HidMsg * ); int ( *read )( int, int, int, HidMsg * ); const char * ( *name )( int ); const char * driver_name; }; typedef struct _Chuck_Hid_Driver Chuck_Hid_Driver; /* functions */ extern void Hid_init(); extern void Hid_poll(); extern void Hid_quit(); extern void Joystick_init(); extern void Joystick_poll(); extern void Joystick_quit(); extern void Joystick_probe(); extern int Joystick_count(); extern int Joystick_open( int js ); extern int Joystick_open_async( int js ); extern int Joystick_open( const char * name ); extern int Joystick_close( int js ); extern int Joystick_send( int js, const HidMsg * msg ); extern const char * Joystick_name( int js ); extern int Joystick_axes( int js ); extern int Joystick_buttons( int js ); extern int Joystick_hats( int js ); extern void Mouse_init(); extern void Mouse_poll(); extern void Mouse_quit(); extern void Mouse_probe(); extern int Mouse_count(); extern int Mouse_open( int m ); extern int Mouse_open( const char * name ); extern int Mouse_close( int m ); extern int Mouse_send( int m, const HidMsg * msg ); extern const char * Mouse_name( int m ); extern int Mouse_buttons( int m ); extern int Mouse_start_cursor_track(); extern int Mouse_stop_cursor_track(); extern void Keyboard_init(); extern void Keyboard_poll(); extern void Keyboard_quit(); extern void Keyboard_probe(); extern int Keyboard_count(); extern int Keyboard_open( int kb ); extern int Keyboard_open( const char * name ); extern int Keyboard_close( int kb ); extern int Keyboard_send( int kb, const HidMsg * msg ); extern const char * Keyboard_name( int kb ); //#define __CK_HID_WIIREMOTE__ extern void WiiRemote_init(); extern void WiiRemote_poll(); extern void WiiRemote_quit(); extern void WiiRemote_probe(); extern int WiiRemote_count(); extern int WiiRemote_open( int wr ); extern int WiiRemote_open( const char * name ); extern int WiiRemote_close( int wr ); extern int WiiRemote_send( int wr, const HidMsg * msg ); extern const char * WiiRemote_name( int wr ); extern void TiltSensor_init(); extern void TiltSensor_quit(); extern void TiltSensor_probe(); extern int TiltSensor_count(); extern int TiltSensor_open( int ts ); extern int TiltSensor_close( int ts ); extern int TiltSensor_read( int ts, int type, int num, HidMsg * msg ); extern const char * TiltSensor_name( int ts ); #endif chuck-1.2.0.8.dfsg/src/util_math.c0000644000175000017500000001145110600421720015260 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_math.c // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip Davidson (philipd@alumni.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #include "util_math.h" #include // windows / visual c++ #ifdef __PLATFORM_WIN32__ //----------------------------------------------------------------------------- // name: round() // desc: ... //----------------------------------------------------------------------------- double round( double a ) { if( a >= 0 ) return (double)(long)( a + .5 ); else return (double)(long)( a - .5 ); } //----------------------------------------------------------------------------- // name: trunc() // desc: ... //----------------------------------------------------------------------------- double trunc( double a ) { return (double)(long)a; } //----------------------------------------------------------------------------- // name: remainder() // desc: ... //----------------------------------------------------------------------------- double remainder( long a, long b ) { long div = a/b; return a - b*div; } #endif // the following 6 functions are // lifted from PD source // specifically x_acoustics.c // http://puredata.info/downloads #define LOGTWO 0.69314718055994528623 #define LOGTEN 2.302585092994 //----------------------------------------------------------------------------- // name: mtof() // desc: midi to freq //----------------------------------------------------------------------------- double mtof( double f ) { if( f <= -1500 ) return (0); else if( f > 1499 ) return (mtof(1499)); // else return (8.17579891564 * exp(.0577622650 * f)); // TODO: optimize else return ( pow(2,(f-69)/12.0) * 440.0 ); } //----------------------------------------------------------------------------- // name: ftom() // desc: freq to midi //----------------------------------------------------------------------------- double ftom( double f ) { // return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500); // TODO: optimize return (f > 0 ? (log(f/440.0) / LOGTWO) * 12.0 + 69 : -1500); } //----------------------------------------------------------------------------- // name: powtodb() // desc: ... //----------------------------------------------------------------------------- double powtodb( double f ) { if( f <= 0 ) return (0); else { double val = 100 + 10./LOGTEN * log(f); return (val < 0 ? 0 : val); } } //----------------------------------------------------------------------------- // name: rmstodb() // desc: ... //----------------------------------------------------------------------------- double rmstodb( double f ) { if( f <= 0 ) return (0); else { double val = 100 + 20./LOGTEN * log(f); return (val < 0 ? 0 : val); } } //----------------------------------------------------------------------------- // name: dbtopow() // desc: ... //----------------------------------------------------------------------------- double dbtopow( double f ) { if( f <= 0 ) return (0); else { if( f > 870 ) f = 870; return (exp((LOGTEN * 0.1) * (f-100.))); } } //----------------------------------------------------------------------------- // name: dbtorms() // desc: ... //----------------------------------------------------------------------------- double dbtorms( double f ) { if( f <= 0 ) return (0); else { if( f > 485 ) f = 485; return (exp((LOGTEN * 0.05) * (f-100.))); } } chuck-1.2.0.8.dfsg/src/util_math.h0000644000175000017500000000410410600421720015262 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_math.h // desc: a mini-compatibility library for math functions. // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Philip Davidson (philipd@alumni.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __UTIL_MATH_H__ #define __UTIL_MATH_H__ #include #if defined (__cplusplus) || defined(_cplusplus) extern "C" { #endif #ifdef __PLATFORM_WIN32__ double round( double a ); double trunc( double a ); double remainder( long a, long b ); #endif // mtof double mtof( double f ); // ftom double ftom( double f ); // powtodb double powtodb( double f ); // rmstodb double rmstodb( double f ); // dbtopow double dbtopow( double f ); // dbtorms double dbtorms( double f ); #if defined (__cplusplus) || defined(_cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/util_network.c0000644000175000017500000002736010600421720016026 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_network.c // desc: sockets // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // // originally randy_socket // author: Peng Bi (pbi@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // date: Winter 2003 //----------------------------------------------------------------------------- #include "util_network.h" #include "chuck_utils.h" #include #if defined(__PLATFORM_WIN32__) #include #else #include #include #include #include #include #include #include #include #endif #ifdef __PLATFORM_WIN32__ static WSADATA g_wsd; static int g_init = 0; #endif #ifndef socklen_t #define socklen_t unsigned int #endif //----------------------------------------------------------------------------- // name: struct ck_socket_ // desc: ... //----------------------------------------------------------------------------- struct ck_socket_ { int sock; int prot; struct sockaddr_in sock_in; socklen_t len; }; //----------------------------------------------------------------------------- // name: ck_udp_create() // desc: create a udp socket //----------------------------------------------------------------------------- ck_socket ck_udp_create( ) { ck_socket sock = NULL; #ifdef __PLATFORM_WIN32__ // winsock init if( g_init == 0 ) if( WSAStartup( MAKEWORD(1,1), &(g_wsd) ) != 0 && WSAStartup( MAKEWORD(1,0), &(g_wsd) ) != 0 ) { fprintf( stderr, "[chuck]: cannot start winsock, networking disabled...\n" ); return NULL; } // count g_init++; #endif sock = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) ); sock->sock = socket( AF_INET, SOCK_DGRAM, 0 ); sock->prot = SOCK_DGRAM; return sock; } //----------------------------------------------------------------------------- // name: ck_tcp_create() // desc: create a tcp socket //----------------------------------------------------------------------------- ck_socket ck_tcp_create( int flags ) { ck_socket sock = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) ); int nd = 1; int ru = 1; #ifdef __PLATFORM_WIN32__ // winsock init if( g_init == 0 ) if( WSAStartup( MAKEWORD(1,1), &(g_wsd) ) != 0 && WSAStartup( MAKEWORD(1,0), &(g_wsd) ) != 0 ) { fprintf( stderr, "[chuck]: cannot start winsock, networking disabled...\n" ); return NULL; } // count g_init++; #endif sock->sock = socket( AF_INET, SOCK_STREAM, 0 ); sock->prot = SOCK_STREAM; if( flags ) setsockopt( sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&ru, sizeof(ru) ); // setsockopt( sock->sock, SOL_SOCKET, SO_REUSEPORT, (const char *)&ru, sizeof(ru) ); setsockopt( sock->sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&nd, sizeof(nd) ); return sock; } //----------------------------------------------------------------------------- // name: ck_connect2() // desc: connect to a server //----------------------------------------------------------------------------- t_CKBOOL ck_connect2( ck_socket sock, const struct sockaddr * addr, int size ) { int ret = connect( sock->sock, addr, size ); return ( ret >= 0 ); } //----------------------------------------------------------------------------- // name: ck_connect() // desc: connect to a server //----------------------------------------------------------------------------- t_CKBOOL ck_connect( ck_socket sock, const char * hostname, int port ) { int ret; struct hostent * host; #ifdef __PLATFORM_WIN32__ memset( &sock->sock_in, 0, sizeof(struct sockaddr_in) ); #else bzero( &sock->sock_in, sizeof(struct sockaddr_in) ); #endif sock->sock_in.sin_family = AF_INET; sock->sock_in.sin_port = htons( (unsigned short)abs(port) ); // lookup name host = gethostbyname( hostname ); if( !host ) { sock->sock_in.sin_addr.s_addr = inet_addr( hostname ); if( sock->sock_in.sin_addr.s_addr == -1 ) return FALSE; } else { #ifdef __PLATFORM_WIN32__ memcpy( (char *)&sock->sock_in.sin_addr, host->h_addr, host->h_length ); #else bcopy( host->h_addr, (char *)&sock->sock_in.sin_addr, host->h_length ); #endif } if( port < 0 ) return TRUE; ret = ck_connect2( sock, (struct sockaddr *)&sock->sock_in, sizeof( struct sockaddr_in ) ); return ( ret >= 0 ); } //----------------------------------------------------------------------------- // name: ck_bind() // desc: bind to a port //----------------------------------------------------------------------------- t_CKBOOL ck_bind( ck_socket sock, int port ) { int ret; #ifdef __PLATFORM_WIN32__ memset( &sock->sock_in, 0, sizeof(struct sockaddr_in) ); #else bzero( &sock->sock_in, sizeof(struct sockaddr_in) ); #endif sock->sock_in.sin_family = AF_INET; sock->sock_in.sin_port = htons( (unsigned short)port ); sock->sock_in.sin_addr.s_addr = htonl( INADDR_ANY ); ret = bind( sock->sock, (struct sockaddr *)&sock->sock_in, sizeof(struct sockaddr_in)); return ( ret >= 0 ); } //----------------------------------------------------------------------------- // name: ck_listen() // desc: ... //----------------------------------------------------------------------------- t_CKBOOL ck_listen( ck_socket sock, int backlog ) { int ret; if( sock->prot != SOCK_STREAM ) return FALSE; ret = listen( sock->sock, backlog ); return ( ret >= 0 ); } //----------------------------------------------------------------------------- // name: ck_accept() // desc: ... //----------------------------------------------------------------------------- ck_socket ck_accept( ck_socket sock ) { ck_socket client; int nd = 1; if( sock->prot != SOCK_STREAM ) return NULL; client = (ck_socket)checked_malloc( sizeof( struct ck_socket_ ) ); client->len = sizeof( client->sock_in ); client->sock = accept( sock->sock, (struct sockaddr *)&client->sock_in, &client->len ); if( client->sock <= 0 ) goto error; client->prot = SOCK_STREAM; setsockopt( client->sock, IPPROTO_TCP, TCP_NODELAY, (const char *)&nd, sizeof(nd) ); #ifdef __PLATFORM_WIN32__ g_init++; #endif return client; error: free( client ); return NULL; } //----------------------------------------------------------------------------- // name: ck_send() // desc: send a datagram //----------------------------------------------------------------------------- int ck_send( ck_socket sock, const char * buffer, int len ) { return send( sock->sock, buffer, len, 0 ); } //----------------------------------------------------------------------------- // name: ck_send2() // desc: send a datagram //----------------------------------------------------------------------------- int ck_send2( ck_socket sock, const char * buffer, int len ) { return sendto( sock->sock, buffer, len, 0, (struct sockaddr *)&sock->sock_in, sizeof(struct sockaddr_in) ); } //----------------------------------------------------------------------------- // name: ck_sendto() // desc: send a datagram //----------------------------------------------------------------------------- int ck_sendto( ck_socket sock, const char * buffer, int len, const struct sockaddr * to, int tolen ) { if( sock->prot == SOCK_STREAM ) return 0; else return sendto( sock->sock, buffer, len, 0, to, tolen ); } //----------------------------------------------------------------------------- // name: ck_recvfrom() // desc: recv a datagram //----------------------------------------------------------------------------- int ck_recvfrom( ck_socket sock, char * buffer, int len, struct sockaddr * from, int * fromlen ) { if( sock->prot == SOCK_STREAM ) { memset( buffer, 0, len ); return 0; } else return recvfrom( sock->sock, buffer, len, 0, from, (unsigned int *)fromlen ); } //----------------------------------------------------------------------------- // name: ck_recv() // desc: recv a datagram //----------------------------------------------------------------------------- int ck_recv( ck_socket sock, char * buffer, int len ) { if( sock->prot == SOCK_STREAM ) { int ret; int togo = len; char * p = buffer; while( togo > 0 ) { ret = recv( sock->sock, p, togo, 0 ); if( ret < 0 ) return 0; // negative is an error message if( ret == 0 ) return len - togo; // zero is end-of-transmission togo -= ret; p += ret; } return len; } else return recv( sock->sock, buffer, len, 0 ); } //----------------------------------------------------------------------------- // name: ck_recv2() // desc: recv a datagram //----------------------------------------------------------------------------- int ck_recv2( ck_socket sock, char * buffer, int len ) { struct sockaddr_in from; unsigned int flen; memset( &from, 0, sizeof(from) ); flen = sizeof(struct sockaddr_in); return recvfrom( sock->sock, buffer, len, 0, (struct sockaddr *)&from, &flen ); } //----------------------------------------------------------------------------- // name: ck_send_timeout() // desc: ... //----------------------------------------------------------------------------- int ck_send_timeout( ck_socket sock, long sec, long usec ) { struct timeval t; t.tv_sec = sec; t.tv_usec = usec; return 0 == setsockopt( sock->sock, SOL_SOCKET, SO_SNDTIMEO, (const char *)&t, sizeof(t) ); } //----------------------------------------------------------------------------- // name: ck_recv_timeout() // desc: ... //----------------------------------------------------------------------------- int ck_recv_timeout( ck_socket sock, long sec, long usec ) { struct timeval t; t.tv_sec = sec; t.tv_usec = usec; return 0 == setsockopt( sock->sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&t, sizeof(t) ); } //----------------------------------------------------------------------------- // name: ck_close() // close the socket //----------------------------------------------------------------------------- void ck_close( ck_socket sock ) { if( !sock ) return; #ifdef __PLATFORM_WIN32__ closesocket( sock->sock ); #else close( sock->sock ); #endif free( sock ); #ifdef __PLATFORM_WIN32__ // uncount g_init--; // close if( g_init == 0 ) WSACleanup(); #endif } chuck-1.2.0.8.dfsg/src/util_network.h0000644000175000017500000000631210600421720016025 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_network.h // desc: sockets // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // // originally 'randy_socket' // author: Peng Bi (pbi@cs.princeton.edu) // Ge Wang (gewang@cs.princeton.edu) // date: Winter 2003 //----------------------------------------------------------------------------- #ifndef __UTIL_NETWORK_H__ #define __UTIL_NETWORK_H__ #ifndef __PLATFORM_WIN32__ #include #include #include #else #include #endif #include "chuck_def.h" #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif // our socket type typedef struct ck_socket_ * ck_socket; // create a UDP socket ck_socket ck_udp_create( ); // create a TCP socket ck_socket ck_tcp_create( int flags ); // connect to a server t_CKBOOL ck_connect( ck_socket sock, const char * hostname, int port ); // connect to a server t_CKBOOL ck_connect2( ck_socket sock, const struct sockaddr * serv_addr, int addrlen); // bind to a port t_CKBOOL ck_bind( ck_socket sock, int port ); // listen (TCP) t_CKBOOL ck_listen( ck_socket sock, int backlog ); // accept (TCP) ck_socket ck_accept( ck_socket sock ); // send int ck_send( ck_socket sock, const char * buffer, int len ); // send using connect/sendto int ck_send2( ck_socket sock, const char * buffer, int len ); // send a datagram int ck_sendto( ck_socket sock, const char * buffer, int len, const struct sockaddr * to, int tolen ); // recv int ck_recv( ck_socket sock, char * buffer, int len ); // recv int ck_recv2( ck_socket sock, char * buffer, int len ); // recv a datagram int ck_recvfrom( ck_socket sock, char * buffer, int len, struct sockaddr * from, int * fromlen ); // send timeout int ck_send_timeout( ck_socket sock, long sec, long usec ); // recv timeout int ck_recv_timeout( ck_socket sock, long sec, long usec ); // close the socket void ck_close( ck_socket sock ); #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/util_raw.c0000644000175000017500000112002510600421720015117 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_raw.c // desc: raw data from STK // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Autumn 2002 //------------------------------------------------------------------------------ #include "util_raw.h" // data for ahh.raw... SAMPLE ahh_data[] = { -619.0f,-1663.0f,-3454.0f,-5317.0f,-6337.0f,-6667.0f,-5952.0f,-2723.0f, 2562.0f,7412.0f,11227.0f,14729.0f,16641.0f,15910.0f,13340.0f,9605.0f, 5268.0f,1887.0f,-177.0f,-2049.0f,-3518.0f,-3831.0f,-3647.0f,-3872.0f, -4378.0f,-4611.0f,-3839.0f,-1824.0f,505.0f,2730.0f,5372.0f,7967.0f, 9003.0f,8047.0f,5951.0f,3059.0f,-691.0f,-4064.0f,-6233.0f,-7582.0f, -7574.0f,-5984.0f,-4032.0f,-2386.0f,-940.0f,-177.0f,-41.0f,514.0f, 1469.0f,2232.0f,3838.0f,6585.0f,8368.0f,8440.0f,7774.0f,6192.0f, 3333.0f,-201.0f,-3261.0f,-4851.0f,-4715.0f,-3221.0f,-932.0f,1678.0f, 4128.0f,5782.0f,5951.0f,4746.0f,3212.0f,1975.0f,1028.0f,393.0f, 248.0f,827.0f,1678.0f,1831.0f,1228.0f,602.0f,144.0f,-515.0f, -1245.0f,-1149.0f,16.0f,1365.0f,2047.0f,2200.0f,2634.0f,3140.0f, 2409.0f,787.0f,-121.0f,40.0f, 0 }; t_CKUINT ahh_size = 92; // data for britestk.raw... SAMPLE britestk_data[] = { 353.0f,1285.0f,-2916.0f,3646.0f,-129.0f,257.0f,-169.0f,-2177.0f, 931.0f,-643.0f,2545.0f,-1045.0f,682.0f,-2980.0f,4047.0f,-5245.0f, 3140.0f,-707.0f,-1687.0f,3485.0f,-1446.0f,2120.0f,-4241.0f,-940.0f, 843.0f,1542.0f,2537.0f,-466.0f,160.0f,-4072.0f,2457.0f,-1486.0f, 1903.0f,48.0f,136.0f,1156.0f,1068.0f,-1759.0f,200.0f,-2024.0f, 1421.0f,361.0f,-65.0f,1084.0f,-25.0f,-3036.0f,3076.0f,-1567.0f, 1799.0f,-1020.0f,1839.0f,-3317.0f,3477.0f,-2434.0f,2096.0f,-860.0f, 64.0f,120.0f,-892.0f,562.0f,176.0f,481.0f,-137.0f,-177.0f, -362.0f,658.0f,-515.0f,1076.0f,473.0f,-498.0f,-523.0f,787.0f, -1173.0f,1301.0f,-2707.0f,2634.0f,-747.0f,1252.0f,-1253.0f,-274.0f, -1687.0f,658.0f,-322.0f,706.0f,-788.0f,1389.0f,-1462.0f,1790.0f, -812.0f,722.0f,257.0f,-169.0f,265.0f,32.0f,-137.0f,562.0f, -523.0f,393.0f,-25.0f,979.0f,-1663.0f,746.0f,-1663.0f,1445.0f, -1591.0f,1951.0f,-563.0f,578.0f,570.0f,1614.0f,-3904.0f,3027.0f, -4145.0f,4280.0f,96.0f,2529.0f,-788.0f,570.0f,-1751.0f,1204.0f, -1904.0f,224.0f,-201.0f,-217.0f,6232.0f,-5614.0f,2738.0f,-3751.0f, 1341.0f,-2024.0f,3919.0f,-2065.0f,2313.0f,-3566.0f,1943.0f,-924.0f, 265.0f,152.0f,136.0f,-1824.0f,4296.0f,-3558.0f,2457.0f,-1318.0f, 120.0f,2650.0f,-4080.0f,2529.0f,80.0f,-1840.0f,771.0f,1309.0f, -1462.0f,1100.0f,-747.0f,-57.0f,-274.0f,80.0f,658.0f,971.0f, -1478.0f,2529.0f,-5036.0f,3316.0f,-169.0f,2417.0f,-1575.0f,1750.0f, -3141.0f,2409.0f,-1045.0f,1317.0f,538.0f,-1125.0f,738.0f,-241.0f, -1920.0f,2401.0f,-2330.0f,602.0f,2345.0f,-900.0f,1815.0f,-2980.0f, 538.0f,-1061.0f,2144.0f,184.0f,1397.0f,-346.0f,-643.0f,-474.0f, 907.0f,-370.0f,1156.0f,-1302.0f,1036.0f,-3165.0f,5830.0f,-6225.0f, 5838.0f,-2779.0f,-683.0f,-49.0f,-266.0f,-274.0f,1742.0f,-1165.0f, 1517.0f,-1366.0f,746.0f,-274.0f,-3872.0f,1782.0f,88.0f,1124.0f, 3413.0f,-1269.0f,-2105.0f,4039.0f,-8779.0f,10689.0f,-5414.0f,1742.0f, 2441.0f,-1735.0f,-121.0f,2867.0f,-3968.0f,827.0f,168.0f,923.0f, -1470.0f,-9.0f,1437.0f,-3173.0f,1172.0f,594.0f,-611.0f,-780.0f, 2497.0f,-1960.0f,3999.0f,-2498.0f,867.0f,1525.0f,-884.0f,754.0f, 666.0f,-386.0f,1003.0f,939.0f,-1085.0f,-193.0f,-980.0f,1044.0f, -1671.0f,3132.0f,-3631.0f,1807.0f,-1928.0f,843.0f,72.0f,305.0f, -153.0f,-338.0f,136.0f,-1310.0f,2280.0f,-1141.0f,754.0f,1052.0f, -410.0f,-595.0f,1293.0f,-1663.0f,385.0f,96.0f,481.0f,2313.0f, -1671.0f,1566.0f,-1631.0f,1028.0f,-1591.0f,2048.0f,-3221.0f,3630.0f, -2113.0f,1044.0f,698.0f,-1061.0f,2843.0f,-3277.0f,24.0f,2031.0f, -2490.0f,2786.0f,1028.0f,-81.0f,1011.0f,-1261.0f,1068.0f,-659.0f, 1204.0f,-1342.0f,2200.0f,-4354.0f,6232.0f,-5558.0f,3204.0f,1100.0f, -2803.0f,578.0f,730.0f,-1607.0f,-161.0f,-1029.0f,931.0f,1108.0f, 1782.0f,-97.0f,-1671.0f,-1229.0f,811.0f,297.0f,827.0f,923.0f, 273.0f,-1037.0f,-41.0f,184.0f,-1655.0f,1461.0f,-1671.0f,1903.0f, -506.0f,72.0f,626.0f,-4707.0f,5348.0f,-4843.0f,4754.0f,-2587.0f, 1525.0f,-932.0f,208.0f,634.0f,72.0f,248.0f,-185.0f,1558.0f, -643.0f,2192.0f,-2354.0f,2738.0f,-1703.0f,658.0f,-346.0f,88.0f, -370.0f,3389.0f,-3173.0f,2031.0f,-1575.0f,-274.0f,289.0f,-667.0f, -338.0f,1180.0f,160.0f,811.0f,401.0f,-1398.0f,-450.0f,313.0f, 1196.0f,-531.0f,1477.0f,-282.0f,923.0f,-241.0f,1582.0f,-3109.0f, 2072.0f,-996.0f,481.0f,-1591.0f,1670.0f,-1205.0f,-290.0f,-97.0f, 1084.0f,-2016.0f,1710.0f,-1559.0f,-233.0f,1485.0f,-1342.0f,650.0f, -249.0f,1790.0f,-555.0f,1453.0f,-2314.0f,2296.0f,-1984.0f,1662.0f, -1053.0f,1485.0f,-763.0f,554.0f,-362.0f,-185.0f,-153.0f,-49.0f, -515.0f,907.0f,136.0f,385.0f,-515.0f,1533.0f,-1229.0f,1060.0f, -1310.0f,1582.0f,-370.0f,899.0f,433.0f,321.0f,353.0f,208.0f, 361.0f,-1245.0f,1967.0f,-1623.0f,2594.0f,-418.0f,232.0f,40.0f, -1486.0f,-788.0f,1453.0f,-266.0f,-1004.0f,2080.0f,-1526.0f,265.0f, 1084.0f,-3735.0f,2987.0f,-2611.0f,2160.0f,-258.0f,-860.0f,4023.0f, -5494.0f,5364.0f,-2522.0f,979.0f,240.0f,-988.0f,1156.0f,-1840.0f, 2521.0f,-1944.0f,1124.0f,-964.0f,-41.0f,522.0f,-2811.0f,3349.0f, -2217.0f,602.0f,650.0f,-924.0f,1517.0f,-2081.0f,2296.0f,-1302.0f, 1084.0f,859.0f,-177.0f,1244.0f,72.0f,-619.0f,1293.0f,-868.0f, 754.0f,-788.0f,2642.0f,-4779.0f,8031.0f,-7968.0f,6047.0f,-2410.0f, -683.0f,1509.0f,-1518.0f,1309.0f,1140.0f,-1133.0f,1156.0f,-1245.0f, -354.0f,1333.0f,-1109.0f,1646.0f,-900.0f,1341.0f,-1711.0f,2843.0f, -3398.0f,3726.0f,-4217.0f,4505.0f,-836.0f,-707.0f,417.0f,-1173.0f, -1486.0f,3220.0f,-2587.0f,2064.0f,-1294.0f,80.0f,48.0f,-506.0f, -836.0f,32.0f,56.0f,1092.0f,329.0f,-298.0f,-217.0f,-571.0f, 192.0f,1244.0f,401.0f,522.0f,-354.0f,289.0f,224.0f,-1631.0f, 1726.0f,-1534.0f,947.0f,1766.0f,361.0f,-1695.0f,1341.0f,-4522.0f, 4136.0f,-1510.0f,2393.0f,-755.0f,1188.0f,-1197.0f,1782.0f,-2169.0f, 505.0f,-812.0f,2313.0f,1252.0f,-1952.0f,6513.0f,-10096.0f,7051.0f, -3486.0f,626.0f,779.0f,-747.0f,1044.0f,2168.0f,-2418.0f,1927.0f, -1840.0f,706.0f,-980.0f,1606.0f,-2699.0f,3565.0f,-3133.0f,1863.0f, -715.0f,-354.0f,2031.0f,-4900.0f,6360.0f,-4032.0f,2329.0f,-1197.0f, 1180.0f,-900.0f,1863.0f,-1350.0f,16.0f,754.0f,-860.0f,-715.0f, 3076.0f,-5446.0f,7453.0f,-7197.0f,5549.0f,-2177.0f,-643.0f,-73.0f, -1896.0f,2698.0f,-836.0f,1654.0f,-1.0f,-539.0f,1991.0f,-2643.0f, 2979.0f,-2996.0f,3758.0f,-2161.0f,1413.0f,754.0f,-1623.0f,2529.0f, -4787.0f,4513.0f,-1872.0f,762.0f,-386.0f,811.0f,-2522.0f,3477.0f, -2860.0f,3116.0f,-1751.0f,939.0f,-1029.0f,1285.0f,-1446.0f,2529.0f, -3647.0f,4280.0f,-1743.0f,883.0f,-169.0f,-1711.0f,1011.0f,-241.0f, 449.0f,-153.0f,1349.0f,-1767.0f,2602.0f,-3068.0f,1742.0f,-876.0f, -579.0f,746.0f,682.0f,-1446.0f,1598.0f,-828.0f,56.0f,562.0f, -1069.0f,1397.0f,-249.0f,-49.0f,1148.0f,329.0f,-916.0f,1911.0f, -1109.0f,-25.0f,353.0f,-555.0f,1670.0f,-362.0f,634.0f,-129.0f, -1037.0f,570.0f,64.0f,-290.0f,1260.0f,-611.0f,-996.0f,1333.0f, -1551.0f,626.0f,-73.0f,-33.0f,1951.0f,1598.0f,-185.0f,-1551.0f, 377.0f,-2065.0f,2473.0f,1598.0f,-2490.0f,2931.0f,-1494.0f,24.0f, -450.0f,-515.0f,-1615.0f,1678.0f,16.0f,1710.0f,-1077.0f,-81.0f, -1253.0f,152.0f,1365.0f,-1559.0f,1646.0f,-651.0f,-490.0f,1799.0f, -1101.0f,811.0f,96.0f,385.0f,-1398.0f,907.0f,626.0f,-1029.0f, 1638.0f,-362.0f,313.0f,843.0f,-1944.0f,2256.0f,-1904.0f,248.0f, 1317.0f,-627.0f,779.0f,-1077.0f,1244.0f,-1743.0f,746.0f,2529.0f, -2257.0f,2730.0f,-2450.0f,2039.0f,-1414.0f,2931.0f,-1791.0f,1710.0f, 88.0f,-996.0f,1927.0f,-1992.0f,1140.0f,-667.0f,1060.0f,754.0f, -57.0f,-1029.0f,-249.0f,-2587.0f,2594.0f,-1020.0f,554.0f,867.0f, -169.0f,1517.0f,-81.0f,-2314.0f,827.0f,-418.0f,1019.0f,-900.0f, 2465.0f,-2040.0f,2015.0f,-1430.0f,-290.0f,1268.0f,-1952.0f,1493.0f, -996.0f,184.0f,1983.0f,-2980.0f,2449.0f,-627.0f,-980.0f,2698.0f, -2563.0f,811.0f,-820.0f,-306.0f,1831.0f,305.0f,168.0f,859.0f, -1020.0f,-225.0f,2176.0f,-2065.0f,1220.0f,995.0f,618.0f,-105.0f, 843.0f,-1422.0f,730.0f,-1117.0f,2570.0f,-1149.0f,666.0f,1542.0f, -4594.0f,3533.0f,-1125.0f,-241.0f,1999.0f,-1920.0f,1276.0f,457.0f, -699.0f,104.0f,-33.0f,-225.0f,1469.0f,-338.0f,963.0f,-707.0f, 16.0f,208.0f,112.0f,-442.0f,1116.0f,-2185.0f,2481.0f,-1438.0f, -105.0f,-298.0f,-225.0f,-298.0f,594.0f,-763.0f,987.0f,449.0f, 128.0f,819.0f,-1840.0f,-121.0f,-249.0f,1566.0f,24.0f,224.0f, 353.0f,-386.0f,441.0f,72.0f,-908.0f,1895.0f,-1061.0f,1236.0f, 923.0f,-964.0f,-25.0f,-1101.0f,771.0f,1373.0f,602.0f,-217.0f, -338.0f,-354.0f,104.0f,369.0f,819.0f,32.0f,538.0f,-298.0f, 1196.0f,-1004.0f,-97.0f,-274.0f,923.0f,931.0f,2280.0f,-2466.0f, 1469.0f,-2474.0f,2015.0f,-1518.0f,2248.0f,-1936.0f,2224.0f,-2900.0f, 3895.0f,-4851.0f,3357.0f,-2932.0f,1341.0f,706.0f,-812.0f,1766.0f, -2201.0f,1333.0f,377.0f,-836.0f,2144.0f,-2113.0f,1582.0f,-2418.0f, 2393.0f,-2105.0f,3421.0f,-3277.0f,2529.0f,-1165.0f,-370.0f,192.0f, -217.0f,-1422.0f,3172.0f,-1783.0f,1831.0f,706.0f,-3261.0f,2305.0f, -1719.0f,1421.0f,192.0f,441.0f,-97.0f,2047.0f,-1808.0f,1429.0f, 257.0f,-1655.0f,3204.0f,-2378.0f,1887.0f,1076.0f,-2273.0f,2706.0f, -1559.0f,666.0f,995.0f,-1591.0f,1052.0f,-65.0f,-675.0f,1525.0f, -1928.0f,2296.0f,-1719.0f,1148.0f,-241.0f,32.0f,-458.0f,1469.0f, -2314.0f,2104.0f,-2169.0f,1582.0f,698.0f,955.0f,-474.0f,-458.0f, -25.0f,48.0f,-338.0f,40.0f,-354.0f,522.0f,1148.0f,-1623.0f, 618.0f,-876.0f,-820.0f,1389.0f,0.0f,1228.0f,-1398.0f,939.0f, -3036.0f,3822.0f,-2281.0f,1911.0f,-57.0f,313.0f,-73.0f,626.0f, -1334.0f,867.0f,-1053.0f,1999.0f,16.0f,1325.0f,-531.0f,-442.0f, 200.0f,136.0f,232.0f,698.0f,-306.0f,-442.0f,2698.0f,-3325.0f, 3324.0f,-1205.0f,883.0f,-1334.0f,2264.0f,-2474.0f,2449.0f,-1518.0f, 240.0f,1622.0f,-1430.0f,1509.0f,-747.0f,-699.0f,803.0f,-723.0f, 1140.0f,-41.0f,337.0f,216.0f,-1952.0f,2425.0f,-1816.0f,1044.0f, -587.0f,1052.0f,-932.0f,578.0f,433.0f,-2129.0f,1927.0f,-1310.0f, 1718.0f,192.0f,-418.0f,48.0f,-884.0f,803.0f,-523.0f,1100.0f, -1310.0f,1148.0f,1236.0f,-2241.0f,1911.0f,-2707.0f,1766.0f,-1141.0f, 2714.0f,-876.0f,883.0f,-667.0f,738.0f,48.0f,-563.0f,128.0f, 377.0f,1116.0f,393.0f,-49.0f,425.0f,-852.0f,730.0f,-57.0f, 1188.0f,-988.0f,1333.0f,-1832.0f,1469.0f,-739.0f,546.0f,-137.0f, -282.0f,1212.0f,-161.0f,-153.0f,-105.0f,-691.0f,1807.0f,-1197.0f, 2730.0f,-1165.0f,-25.0f,-241.0f,-603.0f,939.0f,-659.0f,851.0f, -1109.0f,1999.0f,-1286.0f,48.0f,433.0f,-603.0f,-129.0f,1887.0f, -996.0f,554.0f,-185.0f,-1671.0f,1309.0f,136.0f,1220.0f,-1037.0f, 554.0f,-820.0f,-667.0f,1188.0f,-1269.0f,690.0f,1260.0f,650.0f, 1188.0f,-675.0f,-410.0f,-1133.0f,313.0f,2176.0f,-1518.0f,1309.0f, 281.0f,-675.0f,1381.0f,-2450.0f,2602.0f,-3125.0f,3646.0f,-2169.0f, 1694.0f,32.0f,-1277.0f,457.0f,0.0f,1381.0f,-892.0f,1477.0f, -1253.0f,1132.0f,915.0f,-2378.0f,1927.0f,-442.0f,-426.0f,1654.0f, -523.0f,-314.0f,-193.0f,112.0f,-523.0f,955.0f,-394.0f,24.0f, 1148.0f,289.0f,-611.0f,345.0f,-450.0f,-330.0f,1204.0f,-1318.0f, 931.0f,-249.0f,-129.0f,385.0f,-964.0f,939.0f,232.0f,-1053.0f, 2023.0f,-723.0f,224.0f,562.0f,-707.0f,1260.0f,-290.0f,32.0f, 698.0f,-563.0f,915.0f,-1093.0f,1172.0f,-804.0f,867.0f,-603.0f, 441.0f,353.0f,-523.0f,1036.0f,-217.0f,497.0f,-707.0f,1100.0f, -1245.0f,1028.0f,-169.0f,-683.0f,2224.0f,-434.0f,152.0f,-177.0f, -370.0f,-402.0f,1188.0f,-723.0f,481.0f,497.0f,-97.0f,72.0f, -73.0f,-579.0f,425.0f,-290.0f,1100.0f,1052.0f,-900.0f,8.0f, -571.0f,1212.0f,-1334.0f,1855.0f,-1294.0f,843.0f,-1478.0f,2056.0f, -2779.0f,2377.0f,-1350.0f,473.0f,1622.0f,377.0f,-804.0f,-282.0f, 297.0f,184.0f,522.0f,674.0f,-370.0f,706.0f,-1037.0f,1076.0f, -876.0f,505.0f,-57.0f,112.0f,995.0f,-258.0f,449.0f,-266.0f, 184.0f,634.0f,64.0f,-129.0f,481.0f,24.0f,-450.0f,120.0f, 1646.0f,-1832.0f,2537.0f,-2795.0f,2345.0f,-1992.0f,1381.0f,-651.0f, 224.0f,722.0f,281.0f,481.0f,-1133.0f,1927.0f,-2731.0f,2594.0f, -1607.0f,835.0f,722.0f,-1438.0f,1847.0f,-667.0f,-852.0f,1871.0f, -2530.0f,2698.0f,-2040.0f,698.0f,963.0f,-1277.0f,915.0f,273.0f, -9.0f,1180.0f,-1502.0f,1855.0f,-1735.0f,1437.0f,-57.0f,120.0f, -153.0f,1164.0f,-739.0f,538.0f,-442.0f,257.0f,-73.0f,449.0f, 722.0f,554.0f,-169.0f,160.0f,240.0f,208.0f,-233.0f,16.0f, 1076.0f,-1647.0f,1975.0f,-1012.0f,112.0f,1485.0f,-1077.0f,-667.0f, 1750.0f,-1800.0f,1694.0f,104.0f,-1109.0f,2594.0f,-2008.0f,1943.0f, -1342.0f,-249.0f,-89.0f,-274.0f,1879.0f,-908.0f,1381.0f,-1663.0f, 1285.0f,-1269.0f,1204.0f,-1583.0f,1574.0f,-643.0f,313.0f,-137.0f, 1654.0f,-3020.0f,2240.0f,-474.0f,449.0f,722.0f,562.0f,-1318.0f, 1100.0f,-290.0f,546.0f,-330.0f,754.0f,-386.0f,698.0f,16.0f, -225.0f,-73.0f,433.0f,-113.0f,1252.0f,698.0f,-1567.0f,2489.0f, -2137.0f,1405.0f,48.0f,-418.0f,610.0f,971.0f,-1543.0f,1911.0f, -1856.0f,1702.0f,-1302.0f,1437.0f,-65.0f,425.0f,152.0f,248.0f, -739.0f,1630.0f,-715.0f,-555.0f,2232.0f,-2193.0f,1999.0f,-1398.0f, 714.0f,602.0f,-1004.0f,297.0f,80.0f,24.0f,-370.0f,562.0f, -402.0f,441.0f,457.0f,-1237.0f,1429.0f,-482.0f,-370.0f,1268.0f, -916.0f,1076.0f,-820.0f,385.0f,-290.0f,-49.0f,1686.0f,-1261.0f, 1236.0f,-386.0f,-772.0f,746.0f,-354.0f,1003.0f,-442.0f,867.0f, 0.0f,610.0f,-595.0f,297.0f,257.0f,-185.0f,1678.0f,-1189.0f, 2031.0f,-1928.0f,1068.0f,-73.0f,361.0f,666.0f,-105.0f,337.0f, 64.0f,297.0f,337.0f,224.0f,208.0f,409.0f,-225.0f,248.0f, 232.0f,-515.0f,208.0f,803.0f,-956.0f,1566.0f,-627.0f,-201.0f, 48.0f,409.0f,-249.0f,192.0f,401.0f,-129.0f,425.0f,-137.0f, -225.0f,425.0f,-852.0f,867.0f,-908.0f,1718.0f,-1277.0f,1244.0f, -225.0f,562.0f,-1727.0f,481.0f,-804.0f,1493.0f,-474.0f,232.0f, 1036.0f,-1711.0f,2545.0f,-2466.0f,1638.0f,-515.0f,738.0f,522.0f, 1108.0f,-306.0f,-916.0f,674.0f,-1117.0f,2626.0f,-739.0f,658.0f, 248.0f,-1053.0f,2072.0f,-1599.0f,730.0f,16.0f,1357.0f,-571.0f, 1493.0f,24.0f,-1398.0f,224.0f,682.0f,931.0f,192.0f,64.0f, -402.0f,995.0f,-2330.0f,3156.0f,-2836.0f,2578.0f,-1213.0f,2168.0f, -1318.0f,489.0f,-651.0f,-964.0f,1935.0f,160.0f,-105.0f,1204.0f, -1559.0f,88.0f,-57.0f,112.0f,-651.0f,835.0f,0.0f,1188.0f, -1358.0f,1349.0f,-2048.0f,2015.0f,-1816.0f,1991.0f,-563.0f,-161.0f, 658.0f,-209.0f,56.0f,698.0f,923.0f,-2257.0f,3284.0f,-2129.0f, 819.0f,441.0f,-258.0f,-571.0f,1991.0f,-1438.0f,1381.0f,-233.0f, 875.0f,787.0f,-547.0f,859.0f,-539.0f,979.0f,-298.0f,-137.0f, 1019.0f,80.0f,-940.0f,2256.0f,-2073.0f,2047.0f,-796.0f,72.0f, 1068.0f,-683.0f,706.0f,-282.0f,369.0f,200.0f,706.0f,-635.0f, 1092.0f,-932.0f,80.0f,546.0f,658.0f,-466.0f,1799.0f,-2554.0f, 1919.0f,-1791.0f,1807.0f,-1872.0f,1349.0f,257.0f,353.0f,-370.0f, 1188.0f,-2129.0f,1060.0f,297.0f,-105.0f,762.0f,232.0f,-980.0f, 1124.0f,-386.0f,273.0f,-747.0f,1276.0f,-523.0f,176.0f,875.0f, -73.0f,-667.0f,1919.0f,-1101.0f,489.0f,987.0f,-932.0f,658.0f, 1405.0f,-1711.0f,2369.0f,-1599.0f,1726.0f,-1366.0f,2176.0f,-2209.0f, 1606.0f,-89.0f,-241.0f,706.0f,811.0f,-932.0f,1847.0f,-1069.0f, 1060.0f,152.0f,-523.0f,706.0f,-193.0f,1855.0f,-2546.0f,2505.0f, -1494.0f,554.0f,160.0f,-555.0f,1566.0f,-603.0f,-402.0f,1542.0f, -1454.0f,722.0f,666.0f,-1848.0f,2136.0f,-1004.0f,779.0f,-844.0f, 1823.0f,-715.0f,305.0f,-587.0f,1132.0f,-2153.0f,2851.0f,-2932.0f, 2738.0f,-900.0f,208.0f,361.0f,-89.0f,-89.0f,104.0f,1084.0f, -675.0f,1606.0f,-73.0f,-627.0f,441.0f,618.0f,-667.0f,835.0f, 160.0f,-105.0f,795.0f,-1085.0f,2240.0f,-1607.0f,1790.0f,-948.0f, 1044.0f,-1117.0f,2080.0f,-1117.0f,779.0f,674.0f,-201.0f,-25.0f, 224.0f,200.0f,-177.0f,104.0f,947.0f,80.0f,32.0f,546.0f, -1583.0f,1919.0f,-1342.0f,2192.0f,-1117.0f,1044.0f,-1085.0f,1236.0f, -1358.0f,1702.0f,-876.0f,329.0f,192.0f,128.0f,289.0f,-916.0f, 570.0f,168.0f,-458.0f,947.0f,24.0f,-796.0f,1919.0f,-1872.0f, 2208.0f,-1414.0f,1839.0f,-836.0f,248.0f,-49.0f,626.0f,297.0f, 514.0f,-25.0f,88.0f,-683.0f,522.0f,746.0f,-386.0f,546.0f, 361.0f,-1.0f,586.0f,722.0f,-1390.0f,1807.0f,-627.0f,1228.0f, -1053.0f,2176.0f,-2281.0f,1790.0f,-418.0f,313.0f,939.0f,-1205.0f, 1019.0f,-715.0f,586.0f,465.0f,64.0f,706.0f,385.0f,-635.0f, 1807.0f,-2603.0f,1839.0f,-1543.0f,1220.0f,835.0f,-57.0f,176.0f, 88.0f,-707.0f,489.0f,208.0f,-1261.0f,2353.0f,-763.0f,128.0f, 2570.0f,-4105.0f,3188.0f,-2105.0f,779.0f,1871.0f,-2546.0f,3991.0f, -3301.0f,2337.0f,-659.0f,-81.0f,-386.0f,1509.0f,-1430.0f,1831.0f, -547.0f,-490.0f,1879.0f,-1775.0f,1790.0f,1196.0f,-2820.0f,3686.0f, -2876.0f,1180.0f,1461.0f,-1302.0f,2441.0f,-1454.0f,273.0f,489.0f, -707.0f,-81.0f,1437.0f,-1012.0f,738.0f,1413.0f,-1366.0f,321.0f, 1421.0f,-2169.0f,2810.0f,-2506.0f,3051.0f,-2016.0f,1517.0f,-402.0f, 136.0f,377.0f,570.0f,-1286.0f,979.0f,-1.0f,-185.0f,690.0f, 136.0f,40.0f,1003.0f,-1783.0f,1397.0f,-41.0f,-643.0f,610.0f, 1100.0f,-1414.0f,1357.0f,-1053.0f,1517.0f,-603.0f,497.0f,-17.0f, -65.0f,923.0f,-322.0f,-169.0f,939.0f,-916.0f,1662.0f,-1053.0f, 939.0f,273.0f,-145.0f,562.0f,714.0f,-298.0f,-145.0f,2168.0f, -3237.0f,3469.0f,-1446.0f,457.0f,48.0f,329.0f,-498.0f,-129.0f, 1373.0f,265.0f,-370.0f,1180.0f,-394.0f,698.0f,152.0f,-1494.0f, 1951.0f,-860.0f,497.0f,642.0f,-177.0f,-523.0f,1742.0f,-2346.0f, 2184.0f,-1856.0f,1895.0f,-1221.0f,746.0f,771.0f,-105.0f,-731.0f, 1566.0f,-515.0f,-796.0f,1742.0f,-1534.0f,1517.0f,-153.0f,72.0f, 457.0f,240.0f,208.0f,-97.0f,-1253.0f,3003.0f,-2691.0f,1983.0f, -298.0f,497.0f,827.0f,-1037.0f,1405.0f,-1864.0f,1774.0f,-691.0f, 1678.0f,-41.0f,329.0f,682.0f,-2024.0f,2810.0f,-1928.0f,409.0f, 1317.0f,-1639.0f,4184.0f,-3671.0f,2819.0f,-1502.0f,1726.0f,-2434.0f, 4634.0f,-3848.0f,2915.0f,-1020.0f,-217.0f,1485.0f,-1157.0f,923.0f, -442.0f,-892.0f,1421.0f,-1093.0f,947.0f,473.0f,273.0f,377.0f, -1318.0f,2489.0f,-2916.0f,2473.0f,-1751.0f,2385.0f,-1125.0f,867.0f, 706.0f,-2081.0f,2136.0f,-1149.0f,-723.0f,3003.0f,-3342.0f,3477.0f, -2065.0f,1003.0f,771.0f,-1085.0f,1068.0f,-964.0f,377.0f,329.0f, 281.0f,1357.0f,-386.0f,562.0f,441.0f,-458.0f,-964.0f,3357.0f, -3615.0f,3477.0f,-1101.0f,883.0f,-651.0f,1333.0f,-1061.0f,401.0f, 722.0f,-354.0f,1381.0f,-1478.0f,2537.0f,-2916.0f,3493.0f,-1261.0f, 907.0f,321.0f,-1350.0f,578.0f,947.0f,-1069.0f,1405.0f,-322.0f, 104.0f,433.0f,995.0f,-2161.0f,2682.0f,-1117.0f,184.0f,417.0f, 265.0f,-306.0f,-145.0f,200.0f,-209.0f,835.0f,-258.0f,-129.0f, 0 }; t_CKUINT britestk_size = 2048; // data for dope.raw... SAMPLE dope_data[] = { 8.0f,16.0f,16.0f,16.0f,8.0f,32.0f,32.0f,24.0f, 8.0f,16.0f,24.0f,24.0f,16.0f,16.0f,32.0f,32.0f, 32.0f,40.0f,24.0f,16.0f,16.0f,0.0f,-1.0f,-9.0f, -9.0f,-9.0f,-9.0f,-25.0f,-49.0f,-41.0f,-33.0f,-41.0f, -41.0f,-57.0f,-57.0f,-65.0f,-65.0f,-57.0f,0.0f,32.0f, -258.0f,-563.0f,-619.0f,-1302.0f,-1663.0f,-1245.0f,-1639.0f,-1824.0f, -1944.0f,-2161.0f,-2105.0f,-1647.0f,-1269.0f,-1221.0f,-1109.0f,-1687.0f, -1559.0f,-1165.0f,-1221.0f,-1061.0f,-1165.0f,-1663.0f,-1559.0f,-1037.0f, -1189.0f,-1012.0f,-852.0f,-900.0f,-627.0f,-225.0f,8.0f,-338.0f, -346.0f,-434.0f,-266.0f,530.0f,489.0f,425.0f,-41.0f,-523.0f, -780.0f,-1012.0f,-362.0f,-394.0f,-667.0f,-490.0f,-739.0f,-1149.0f, -691.0f,-217.0f,-266.0f,-177.0f,88.0f,-249.0f,-900.0f,-619.0f, -908.0f,-1269.0f,-1438.0f,-1639.0f,-1526.0f,-1775.0f,-1583.0f,-1534.0f, -1502.0f,-1037.0f,-747.0f,-137.0f,184.0f,-17.0f,240.0f,345.0f, 112.0f,345.0f,465.0f,594.0f,281.0f,-17.0f,-193.0f,-563.0f, -370.0f,-25.0f,24.0f,96.0f,-394.0f,-490.0f,-81.0f,104.0f, 489.0f,899.0f,1100.0f,714.0f,1036.0f,1148.0f,514.0f,393.0f, -17.0f,-113.0f,305.0f,56.0f,-41.0f,104.0f,8.0f,-89.0f, 505.0f,1060.0f,610.0f,923.0f,1397.0f,899.0f,489.0f,96.0f, -25.0f,112.0f,682.0f,1052.0f,642.0f,353.0f,-1.0f,0.0f, 682.0f,899.0f,1028.0f,538.0f,-466.0f,-370.0f,-523.0f,-402.0f, 514.0f,96.0f,-282.0f,289.0f,690.0f,1341.0f,1405.0f,1437.0f, 618.0f,-868.0f,-410.0f,-482.0f,-956.0f,329.0f,449.0f,192.0f, 1060.0f,738.0f,859.0f,995.0f,353.0f,602.0f,16.0f,-17.0f, 602.0f,56.0f,690.0f,1076.0f,779.0f,1477.0f,722.0f,-57.0f, -354.0f,-1567.0f,-1101.0f,-763.0f,-1125.0f,-105.0f,64.0f,248.0f, 1132.0f,1333.0f,1718.0f,1244.0f,305.0f,8.0f,-418.0f,200.0f, 1132.0f,1710.0f,2056.0f,1525.0f,1268.0f,971.0f,1036.0f,1686.0f, 1815.0f,1469.0f,1341.0f,1622.0f,1678.0f,2240.0f,3300.0f,3790.0f, 3638.0f,3590.0f,3276.0f,2160.0f,1574.0f,1598.0f,1164.0f,1373.0f, 1550.0f,907.0f,1156.0f,1268.0f,1485.0f,1694.0f,1349.0f,698.0f, 144.0f,32.0f,-145.0f,248.0f,650.0f,248.0f,-241.0f,-490.0f, -691.0f,-611.0f,96.0f,265.0f,-515.0f,-1342.0f,-1743.0f,-1623.0f, -1687.0f,-1061.0f,-563.0f,-1245.0f,-844.0f,-169.0f,618.0f,1453.0f, 1140.0f,417.0f,-129.0f,-699.0f,-1534.0f,-651.0f,425.0f,248.0f, 1052.0f,1517.0f,987.0f,963.0f,698.0f,650.0f,200.0f,425.0f, 313.0f,-900.0f,-290.0f,-121.0f,417.0f,1574.0f,1582.0f,1790.0f, 979.0f,570.0f,1381.0f,1590.0f,2305.0f,2345.0f,2023.0f,2465.0f, 2513.0f,2529.0f,2907.0f,2843.0f,2144.0f,2401.0f,2497.0f,1509.0f, 1132.0f,658.0f,473.0f,1084.0f,602.0f,409.0f,80.0f,-996.0f, -884.0f,-1045.0f,-1181.0f,-1534.0f,-2482.0f,-1422.0f,-1269.0f,-2691.0f, -2579.0f,-2924.0f,-3534.0f,-1920.0f,-643.0f,-956.0f,-1069.0f,-1165.0f, -1615.0f,-1671.0f,-113.0f,409.0f,80.0f,433.0f,8.0f,803.0f, 1228.0f,570.0f,1373.0f,1349.0f,658.0f,1774.0f,2200.0f,1461.0f, 1373.0f,562.0f,465.0f,1807.0f,1935.0f,2465.0f,3252.0f,2819.0f, 2794.0f,2722.0f,2867.0f,3204.0f,3204.0f,3316.0f,2465.0f,1550.0f, 2056.0f,1750.0f,1758.0f,2594.0f,2545.0f,2610.0f,2481.0f,2072.0f, 1807.0f,947.0f,562.0f,642.0f,-667.0f,-1695.0f,-1703.0f,-3197.0f, -4932.0f,-4281.0f,-4072.0f,-4273.0f,-3342.0f,-3791.0f,-4225.0f,-4474.0f, -5590.0f,-4803.0f,-4072.0f,-3751.0f,-2306.0f,-2137.0f,-1053.0f,546.0f, 923.0f,1533.0f,1831.0f,1525.0f,963.0f,586.0f,1132.0f,1285.0f, -233.0f,-547.0f,-490.0f,-490.0f,1116.0f,1718.0f,1935.0f,2152.0f, 1807.0f,1927.0f,2650.0f,3798.0f,3871.0f,2786.0f,2264.0f,2128.0f, 2626.0f,3453.0f,4112.0f,4618.0f,3606.0f,3003.0f,3341.0f,2802.0f, 2810.0f,2931.0f,2015.0f,891.0f,289.0f,883.0f,1477.0f,1622.0f, 1678.0f,481.0f,-980.0f,-2105.0f,-3221.0f,-3735.0f,-5213.0f,-6570.0f, -6907.0f,-7181.0f,-6337.0f,-5293.0f,-5542.0f,-5526.0f,-5550.0f,-6402.0f, -5727.0f,-4129.0f,-3494.0f,-2876.0f,-1984.0f,-1551.0f,-1061.0f,554.0f, 1999.0f,2007.0f,2184.0f,1887.0f,1260.0f,1453.0f,2031.0f,1517.0f, 56.0f,-836.0f,-1181.0f,-884.0f,184.0f,1517.0f,2208.0f,2208.0f, 2120.0f,2987.0f,4168.0f,3943.0f,3284.0f,2200.0f,1285.0f,1742.0f, 2337.0f,3164.0f,3638.0f,3188.0f,2746.0f,2192.0f,2160.0f,2481.0f, 2128.0f,1140.0f,-306.0f,-1245.0f,-1518.0f,-1181.0f,522.0f,1750.0f, 939.0f,-89.0f,-1077.0f,-2996.0f,-4530.0f,-5197.0f,-6891.0f,-8931.0f, -9357.0f,-8867.0f,-8305.0f,-7871.0f,-7108.0f,-6610.0f,-6859.0f,-7148.0f, -6297.0f,-4675.0f,-3888.0f,-2779.0f,-1607.0f,-611.0f,56.0f,706.0f, 3148.0f,5726.0f,6609.0f,6441.0f,6039.0f,3991.0f,1815.0f,1212.0f, 690.0f,987.0f,2023.0f,2562.0f,3108.0f,4007.0f,4585.0f,5405.0f, 5324.0f,4457.0f,4553.0f,3614.0f,2256.0f,2537.0f,2746.0f,1951.0f, 2168.0f,3421.0f,4160.0f,4738.0f,4899.0f,4304.0f,3067.0f,1373.0f, -161.0f,-1374.0f,-2105.0f,-1912.0f,-699.0f,0.0f,-506.0f,-924.0f, -1703.0f,-3711.0f,-5398.0f,-6787.0f,-8819.0f,-10602.0f,-11252.0f,-10947.0f, -10321.0f,-9389.0f,-8458.0f,-7566.0f,-6177.0f,-4868.0f,-3944.0f,-3109.0f, -2297.0f,-2225.0f,-2121.0f,-1462.0f,-378.0f,2039.0f,4762.0f,7236.0f, 8585.0f,7878.0f,6802.0f,5340.0f,2827.0f,2120.0f,3308.0f,3172.0f, 3027.0f,4545.0f,4899.0f,4577.0f,6272.0f,8465.0f,8979.0f,8143.0f, 7308.0f,5903.0f,3606.0f,2738.0f,2425.0f,1268.0f,1405.0f,2521.0f, 3140.0f,3726.0f,4465.0f,4465.0f,2891.0f,779.0f,-908.0f,-2723.0f, -3904.0f,-3695.0f,-3671.0f,-4410.0f,-4643.0f,-4586.0f,-5398.0f,-6610.0f, -7678.0f,-9229.0f,-11148.0f,-12297.0f,-12409.0f,-12248.0f,-11831.0f,-10843.0f, -9911.0f,-8787.0f,-7301.0f,-5735.0f,-3759.0f,-2137.0f,-595.0f,915.0f, 1678.0f,3067.0f,5099.0f,7019.0f,9236.0f,11163.0f,11404.0f,10352.0f, 9244.0f,7870.0f,6200.0f,5501.0f,5678.0f,5646.0f,5999.0f,6625.0f, 6601.0f,6714.0f,7147.0f,7348.0f,7019.0f,6216.0f,4995.0f,2875.0f, 1244.0f,457.0f,-651.0f,-1053.0f,-796.0f,-820.0f,-892.0f,-1149.0f, -1663.0f,-2731.0f,-4426.0f,-6040.0f,-7309.0f,-7863.0f,-7719.0f,-7992.0f, -8361.0f,-8458.0f,-9020.0f,-9582.0f,-9927.0f,-10433.0f,-10907.0f,-11220.0f, -11204.0f,-11060.0f,-10642.0f,-9710.0f,-8570.0f,-7237.0f,-5542.0f,-3655.0f, -1599.0f,441.0f,2152.0f,3308.0f,4328.0f,5694.0f,7059.0f,8858.0f, 10914.0f,12079.0f,12207.0f,11701.0f,10762.0f,9581.0f,8384.0f,7718.0f, 7300.0f,7220.0f,7533.0f,7485.0f,7364.0f,7091.0f,6296.0f,5670.0f, 5067.0f,3975.0f,2305.0f,305.0f,-1639.0f,-3358.0f,-4313.0f,-4627.0f, -4538.0f,-3936.0f,-3566.0f,-4105.0f,-5116.0f,-6257.0f,-7566.0f,-8650.0f, -9036.0f,-8947.0f,-8947.0f,-8972.0f,-8666.0f,-8466.0f,-8401.0f,-8168.0f, -8112.0f,-8273.0f,-8474.0f,-8811.0f,-8875.0f,-8393.0f,-7526.0f,-6345.0f, -4859.0f,-3141.0f,-1109.0f,907.0f,2529.0f,3983.0f,5172.0f,5798.0f, 6208.0f,7188.0f,8481.0f,10007.0f,11773.0f,12858.0f,12834.0f,11902.0f, 10280.0f,8481.0f,6882.0f,5678.0f,5324.0f,5662.0f,6280.0f,6601.0f, 6047.0f,4577.0f,2955.0f,1799.0f,754.0f,-346.0f,-1599.0f,-3374.0f, -5639.0f,-7558.0f,-8642.0f,-8723.0f,-7727.0f,-6313.0f,-5446.0f,-5341.0f, -5847.0f,-6739.0f,-7558.0f,-7863.0f,-7606.0f,-7164.0f,-6899.0f,-6642.0f, -6305.0f,-5879.0f,-5141.0f,-4217.0f,-3582.0f,-3309.0f,-3430.0f,-4024.0f, -4458.0f,-4305.0f,-3695.0f,-2627.0f,-1101.0f,714.0f,2586.0f,4553.0f, 6376.0f,7886.0f,8987.0f,9179.0f,9067.0f,9059.0f,9220.0f,10239.0f, 11404.0f,12047.0f,11902.0f,10818.0f,9067.0f,6995.0f,4842.0f,2955.0f, 2031.0f,2056.0f,2562.0f,2907.0f,2176.0f,361.0f,-1711.0f,-3607.0f, -4972.0f,-5526.0f,-5855.0f,-6506.0f,-7413.0f,-8562.0f,-9486.0f,-9486.0f, -8650.0f,-7430.0f,-6169.0f,-5293.0f,-4932.0f,-4916.0f,-4908.0f,-4562.0f, -3856.0f,-2892.0f,-1880.0f,-1390.0f,-1302.0f,-1173.0f,-1286.0f,-1342.0f, -1181.0f,-1302.0f,-1454.0f,-1229.0f,-1165.0f,-1077.0f,-193.0f,883.0f, 1790.0f,2979.0f,3975.0f,4907.0f,6168.0f,6947.0f,7613.0f,8095.0f, 8031.0f,8175.0f,8505.0f,9187.0f,10239.0f,10930.0f,10617.0f,9308.0f, 7396.0f,4867.0f,2031.0f,-434.0f,-2000.0f,-2354.0f,-1751.0f,-1093.0f, -868.0f,-1382.0f,-2803.0f,-4570.0f,-6032.0f,-6899.0f,-7365.0f,-7751.0f, -8056.0f,-8490.0f,-8867.0f,-8514.0f,-7413.0f,-5855.0f,-3992.0f,-2185.0f, -1029.0f,-458.0f,-209.0f,-217.0f,-274.0f,8.0f,449.0f,674.0f, 819.0f,779.0f,377.0f,80.0f,-201.0f,-836.0f,-1045.0f,-844.0f, -1109.0f,-1149.0f,-506.0f,-49.0f,682.0f,1654.0f,2015.0f,2778.0f, 3702.0f,4031.0f,4650.0f,4955.0f,4995.0f,5806.0f,6609.0f,7533.0f, 8858.0f,9485.0f,9179.0f,8368.0f,6457.0f,3445.0f,473.0f,-2370.0f, -4362.0f,-4024.0f,-2587.0f,-1277.0f,128.0f,297.0f,-1053.0f,-2820.0f, -4578.0f,-5807.0f,-6530.0f,-7213.0f,-7622.0f,-8192.0f,-8618.0f,-7927.0f, -6450.0f,-4442.0f,-1727.0f,554.0f,1670.0f,2200.0f,2048.0f,1084.0f, 449.0f,425.0f,265.0f,265.0f,425.0f,297.0f,297.0f,538.0f, 321.0f,-169.0f,-515.0f,-1213.0f,-2289.0f,-2908.0f,-2980.0f,-2611.0f, -1575.0f,-362.0f,1052.0f,2947.0f,4353.0f,5364.0f,6457.0f,6569.0f, 6481.0f,7324.0f,7549.0f,8111.0f,9814.0f,10464.0f,10023.0f,8834.0f, 6208.0f,3011.0f,232.0f,-2587.0f,-4321.0f,-3679.0f,-2546.0f,-1687.0f, -924.0f,-1518.0f,-3125.0f,-4980.0f,-6562.0f,-7438.0f,-8144.0f,-8345.0f, -8096.0f,-8337.0f,-7911.0f,-6410.0f,-4835.0f,-2667.0f,-81.0f,1646.0f, 2618.0f,3292.0f,3156.0f,2562.0f,2433.0f,2433.0f,1991.0f,1445.0f, 1100.0f,803.0f,578.0f,176.0f,-482.0f,-1141.0f,-1687.0f,-2330.0f, -3020.0f,-3325.0f,-3020.0f,-2362.0f,-1478.0f,-33.0f,1766.0f,3477.0f, 5083.0f,6087.0f,6505.0f,6850.0f,6409.0f,6119.0f,6794.0f,7565.0f, 8722.0f,9685.0f,9477.0f,8328.0f,6079.0f,2706.0f,-739.0f,-3735.0f, -5815.0f,-5960.0f,-4924.0f,-3775.0f,-2603.0f,-2579.0f,-3904.0f,-5438.0f, -6747.0f,-7558.0f,-7670.0f,-7164.0f,-6418.0f,-5968.0f,-5398.0f,-4394.0f, -3181.0f,-1310.0f,939.0f,2802.0f,4272.0f,5356.0f,5662.0f,5509.0f, 5485.0f,5260.0f,4449.0f,3437.0f,2176.0f,610.0f,-691.0f,-1783.0f, -2763.0f,-3197.0f,-3430.0f,-3807.0f,-4016.0f,-4169.0f,-3968.0f,-3342.0f, -2619.0f,-1374.0f,313.0f,2184.0f,3879.0f,4931.0f,5846.0f,6047.0f, 5525.0f,5694.0f,6023.0f,6698.0f,8352.0f,9533.0f,9709.0f,8979.0f, 6898.0f,3838.0f,144.0f,-3671.0f,-6281.0f,-6940.0f,-6072.0f,-4321.0f, -2828.0f,-2297.0f,-3028.0f,-4892.0f,-6546.0f,-7405.0f,-7510.0f,-6650.0f, -5655.0f,-4843.0f,-4096.0f,-3615.0f,-2779.0f,-1253.0f,787.0f,3180.0f, 5316.0f,6979.0f,7975.0f,8007.0f,7565.0f,6641.0f,5083.0f,3357.0f, 1477.0f,-458.0f,-1743.0f,-2595.0f,-3510.0f,-4000.0f,-4490.0f,-5213.0f, -5647.0f,-5928.0f,-5550.0f,-4506.0f,-3502.0f,-1888.0f,-177.0f,1220.0f, 3180.0f,4690.0f,5533.0f,6545.0f,6666.0f,6352.0f,6706.0f,7067.0f, 7886.0f,9115.0f,9750.0f,9468.0f,8023.0f,5405.0f,1943.0f,-2057.0f, -5606.0f,-7614.0f,-7960.0f,-6964.0f,-5382.0f,-4177.0f,-3880.0f,-4755.0f, -6217.0f,-7285.0f,-7590.0f,-6843.0f,-5382.0f,-3968.0f,-2715.0f,-1960.0f, -1543.0f,-691.0f,682.0f,2674.0f,5075.0f,7188.0f,8722.0f,9388.0f, 8987.0f,7846.0f,6047.0f,3855.0f,1646.0f,-466.0f,-2145.0f,-3366.0f, -4514.0f,-5446.0f,-6281.0f,-7116.0f,-7462.0f,-7486.0f,-6964.0f,-5727.0f, -4289.0f,-2530.0f,-603.0f,1148.0f,3092.0f,4698.0f,5878.0f,7043.0f, 7429.0f,7292.0f,7228.0f,6963.0f,6963.0f,7653.0f,8376.0f,8738.0f, 8577.0f,7196.0f,4497.0f,859.0f,-3293.0f,-6996.0f,-9277.0f,-9670.0f, -8674.0f,-7333.0f,-6056.0f,-5446.0f,-5984.0f,-6779.0f,-7293.0f,-7173.0f, -5871.0f,-3960.0f,-1936.0f,-129.0f,883.0f,1413.0f,1726.0f,2264.0f, 3646.0f,5356.0f,7204.0f,8697.0f,8818.0f,8224.0f,7292.0f,5445.0f, 3011.0f,345.0f,-2193.0f,-4129.0f,-5566.0f,-6763.0f,-7638.0f,-8160.0f, -8458.0f,-8337.0f,-7630.0f,-6522.0f,-5076.0f,-3342.0f,-1615.0f,168.0f, 1807.0f,3333.0f,4939.0f,6095.0f,7091.0f,7846.0f,7710.0f,7260.0f, 7011.0f,6786.0f,6826.0f,7429.0f,7902.0f,7790.0f,6971.0f,5019.0f, 1815.0f,-2137.0f,-5968.0f,-9028.0f,-10498.0f,-10128.0f,-8931.0f,-7598.0f, -6377.0f,-5960.0f,-6177.0f,-6257.0f,-5783.0f,-4305.0f,-2089.0f,257.0f, 2393.0f,3718.0f,4136.0f,4176.0f,4240.0f,4842.0f,6007.0f,7284.0f, 8432.0f,8922.0f,8344.0f,6931.0f,4505.0f,1293.0f,-1591.0f,-4048.0f, -6128.0f,-7566.0f,-8530.0f,-9237.0f,-9678.0f,-9686.0f,-9277.0f,-8297.0f, -6851.0f,-5165.0f,-3085.0f,-980.0f,1028.0f,2979.0f,4778.0f,6497.0f, 7653.0f,8304.0f,8561.0f,8167.0f,7549.0f,7115.0f,6658.0f,6465.0f, 6682.0f,6561.0f,6039.0f,4923.0f,2843.0f,-185.0f,-3799.0f,-7052.0f, -9478.0f,-10489.0f,-10008.0f,-8931.0f,-7751.0f,-6843.0f,-6418.0f,-6257.0f, -5751.0f,-4450.0f,-2121.0f,738.0f,3300.0f,5300.0f,6240.0f,6296.0f, 6039.0f,5742.0f,5967.0f,6601.0f,7139.0f,7348.0f,6802.0f,5445.0f, 3413.0f,795.0f,-1856.0f,-4305.0f,-6361.0f,-7735.0f,-8626.0f,-9212.0f, -9542.0f,-9574.0f,-9116.0f,-8136.0f,-6586.0f,-4635.0f,-2490.0f,-571.0f, 1148.0f,3051.0f,4738.0f,5943.0f,7107.0f,8047.0f,8400.0f,8529.0f, 8087.0f,7059.0f,6015.0f,4939.0f,4216.0f,3903.0f,3477.0f,2899.0f, 1790.0f,-209.0f,-3004.0f,-5976.0f,-8393.0f,-10040.0f,-10377.0f,-9566.0f, -8393.0f,-7060.0f,-5847.0f,-5092.0f,-4225.0f,-2988.0f,-1229.0f,1309.0f, 3935.0f,6184.0f,7766.0f,8304.0f,8192.0f,7621.0f,6906.0f,6360.0f, 5710.0f,4971.0f,3879.0f,2232.0f,305.0f,-1912.0f,-4064.0f,-5831.0f, -7148.0f,-7927.0f,-8265.0f,-8377.0f,-8409.0f,-8184.0f,-7614.0f,-6763.0f, -5261.0f,-3301.0f,-1213.0f,1204.0f,3445.0f,5212.0f,6778.0f,7694.0f, 8095.0f,8344.0f,7991.0f,7260.0f,6368.0f,5099.0f,3887.0f,2851.0f, 2272.0f,2248.0f,2144.0f,1951.0f,1325.0f,-258.0f,-2691.0f,-5486.0f, -7839.0f,-9461.0f,-9959.0f,-9237.0f,-8048.0f,-6819.0f,-5582.0f,-4691.0f, -3775.0f,-2330.0f,-458.0f,2072.0f,4690.0f,6834.0f,8352.0f,8818.0f, 8513.0f,7758.0f,6698.0f,5726.0f,4666.0f,3437.0f,1935.0f,32.0f, -2057.0f,-4265.0f,-6169.0f,-7454.0f,-8225.0f,-8201.0f,-7743.0f,-7277.0f, -6667.0f,-6136.0f,-5470.0f,-4498.0f,-3229.0f,-1342.0f,795.0f,2939.0f, 5043.0f,6585.0f,7485.0f,7894.0f,7758.0f,7139.0f,6272.0f,5372.0f, 4353.0f,3300.0f,2465.0f,1694.0f,1156.0f,1196.0f,1028.0f,754.0f, 377.0f,-1181.0f,-3205.0f,-5309.0f,-7550.0f,-8859.0f,-9188.0f,-8755.0f, -7638.0f,-6337.0f,-4988.0f,-3743.0f,-2482.0f,-948.0f,779.0f,2963.0f, 5236.0f,7067.0f,8489.0f,8954.0f,8569.0f,7838.0f,6505.0f,5083.0f, 3670.0f,1935.0f,152.0f,-1775.0f,-3775.0f,-5582.0f,-7044.0f,-7944.0f, -8313.0f,-7984.0f,-7205.0f,-6273.0f,-5004.0f,-3831.0f,-2651.0f,-1358.0f, -81.0f,1574.0f,3252.0f,4802.0f,6208.0f,6882.0f,6971.0f,6601.0f, 5533.0f,4280.0f,3284.0f,2353.0f,1831.0f,1879.0f,1999.0f,2489.0f, 3132.0f,3003.0f,2578.0f,1533.0f,-539.0f,-2739.0f,-5028.0f,-7100.0f, -8184.0f,-8578.0f,-8297.0f,-7550.0f,-6779.0f,-5719.0f,-4691.0f,-3494.0f, -1647.0f,497.0f,3003.0f,5445.0f,7212.0f,8336.0f,8561.0f,8015.0f, 7115.0f,5726.0f,4120.0f,2489.0f,738.0f,-988.0f,-2651.0f,-4113.0f, -5333.0f,-6080.0f,-6313.0f,-6209.0f,-5695.0f,-5036.0f,-4378.0f,-3574.0f, -2908.0f,-2040.0f,-844.0f,337.0f,1726.0f,3003.0f,3951.0f,4634.0f, 4786.0f,4529.0f,4071.0f,3341.0f,2553.0f,1991.0f,1903.0f,2256.0f, 2915.0f,4047.0f,4947.0f,5083.0f,4706.0f,3565.0f,1413.0f,-1277.0f, -3735.0f,-5767.0f,-7124.0f,-7518.0f,-7526.0f,-7301.0f,-6996.0f,-6650.0f, -5984.0f,-4996.0f,-3334.0f,-731.0f,1863.0f,3557.0f,4489.0f,5220.0f, 5814.0f,5943.0f,5629.0f,5220.0f,4786.0f,4047.0f,2843.0f,1236.0f, -699.0f,-2635.0f,-4169.0f,-5189.0f,-5655.0f,-5574.0f,-5325.0f,-5068.0f, -4851.0f,-4635.0f,-4209.0f,-3446.0f,-2225.0f,-643.0f,1244.0f,2971.0f, 4264.0f,5276.0f,5654.0f,5533.0f,5413.0f,4931.0f,4216.0f,3782.0f, 3349.0f,2971.0f,3084.0f,3622.0f,4144.0f,4353.0f,4216.0f,3533.0f, 1911.0f,-563.0f,-3036.0f,-5125.0f,-6851.0f,-7606.0f,-7622.0f,-7381.0f, -6859.0f,-6233.0f,-5502.0f,-4386.0f,-2755.0f,-531.0f,2128.0f,4545.0f, 6473.0f,7734.0f,8119.0f,7951.0f,7348.0f,6376.0f,5300.0f,4007.0f, 2296.0f,409.0f,-1727.0f,-3783.0f,-5382.0f,-6610.0f,-7084.0f,-6883.0f, -6522.0f,-5783.0f,-4827.0f,-4080.0f,-3125.0f,-1767.0f,-266.0f,1437.0f, 3324.0f,4794.0f,5726.0f,6071.0f,5670.0f,4907.0f,3919.0f,2770.0f, 1774.0f,1003.0f,867.0f,1236.0f,1967.0f,3228.0f,4208.0f,4425.0f, 4192.0f,3043.0f,771.0f,-1808.0f,-4249.0f,-6450.0f,-7662.0f,-8088.0f, -8088.0f,-7333.0f,-6787.0f,-6016.0f,-4715.0f,-3366.0f,-1221.0f,1550.0f, 4071.0f,6232.0f,7782.0f,8191.0f,7894.0f,7083.0f,5814.0f,4457.0f, 3092.0f,1493.0f,-370.0f,-2225.0f,-4088.0f,-5566.0f,-6361.0f,-6659.0f, -6345.0f,-5598.0f,-4932.0f,-4281.0f,-3486.0f,-2771.0f,-1912.0f,-490.0f, 1044.0f,2385.0f,3686.0f,4545.0f,4794.0f,4778.0f,4529.0f,4136.0f, 3557.0f,2786.0f,2080.0f,1333.0f,835.0f,883.0f,1301.0f,2104.0f, 2955.0f,3381.0f,3212.0f,2096.0f,64.0f,-2289.0f,-4675.0f,-6787.0f, -7823.0f,-7944.0f,-7662.0f,-6723.0f,-5647.0f,-4787.0f,-3639.0f,-2161.0f, -354.0f,1879.0f,4168.0f,6200.0f,7637.0f,8191.0f,7910.0f,6979.0f, 5549.0f,3967.0f,2313.0f,570.0f,-1141.0f,-2771.0f,-4458.0f,-5920.0f, -6787.0f,-7173.0f,-7036.0f,-6273.0f,-5341.0f,-4321.0f,-3125.0f,-2008.0f, -804.0f,779.0f,2433.0f,3838.0f,5059.0f,5895.0f,5927.0f,5437.0f, 4770.0f,3758.0f,2658.0f,1758.0f,787.0f,-129.0f,-555.0f,-619.0f, -201.0f,698.0f,1839.0f,2682.0f,2802.0f,2216.0f,738.0f,-1430.0f, -3687.0f,-5703.0f,-7052.0f,-7502.0f,-7173.0f,-6305.0f,-5301.0f,-4233.0f, -3052.0f,-1783.0f,-193.0f,1766.0f,3790.0f,5790.0f,7404.0f,8191.0f, 8191.0f,7437.0f,5895.0f,3991.0f,1951.0f,-153.0f,-2040.0f,-3623.0f, -5141.0f,-6337.0f,-7084.0f,-7526.0f,-7373.0f,-6610.0f,-5574.0f,-4169.0f, -2450.0f,-780.0f,955.0f,2562.0f,3710.0f,4650.0f,5220.0f,5340.0f, 5324.0f,4915.0f,4104.0f,3164.0f,1951.0f,489.0f,-755.0f,-1639.0f, -2040.0f,-1599.0f,-378.0f,1260.0f,2778.0f,3678.0f,3847.0f,2867.0f, 891.0f,-1205.0f,-3277.0f,-4819.0f,-5422.0f,-5759.0f,-5719.0f,-5791.0f, -6209.0f,-5976.0f,-5365.0f,-4177.0f,-1751.0f,1060.0f,3606.0f,5790.0f, 7043.0f,7316.0f,7003.0f,6224.0f,5429.0f,4513.0f,3132.0f,1421.0f, -627.0f,-3044.0f,-5253.0f,-6819.0f,-7807.0f,-7968.0f,-7365.0f,-6498.0f, -5398.0f,-4129.0f,-2868.0f,-1446.0f,176.0f,1911.0f,3686.0f,5132.0f, 6047.0f,6497.0f,6224.0f,5429.0f,4521.0f,3300.0f,1943.0f,674.0f, -466.0f,-1366.0f,-1840.0f,-1454.0f,-563.0f,730.0f,2529.0f,3702.0f, 4015.0f,3638.0f,1999.0f,-121.0f,-1936.0f,-3534.0f,-4715.0f,-5365.0f, -5887.0f,-6586.0f,-7156.0f,-7253.0f,-6650.0f,-5197.0f,-2852.0f,-65.0f, 2545.0f,4642.0f,6160.0f,7035.0f,7155.0f,6963.0f,6609.0f,5581.0f, 3951.0f,2136.0f,-113.0f,-2803.0f,-4988.0f,-6610.0f,-7759.0f,-7871.0f, -7229.0f,-6185.0f,-4940.0f,-3663.0f,-2081.0f,-707.0f,273.0f,1879.0f, 3011.0f,2851.0f,3124.0f,3581.0f,3132.0f,2730.0f,2553.0f,1887.0f, 1076.0f,489.0f,-73.0f,-362.0f,-217.0f,128.0f,819.0f,1839.0f, 2810.0f,3084.0f,2441.0f,1622.0f,666.0f,-1149.0f,-3117.0f,-4691.0f, -6185.0f,-6972.0f,-6988.0f,-6642.0f,-5711.0f,-4434.0f,-3077.0f,-1559.0f, 16.0f,1574.0f,2931.0f,4208.0f,5421.0f,6328.0f,6866.0f,6722.0f, 5903.0f,4746.0f,3284.0f,1726.0f,257.0f,-1117.0f,-2273.0f,-3422.0f, -4482.0f,-5390.0f,-6329.0f,-6843.0f,-6811.0f,-6313.0f,-5317.0f,-3920.0f, -2129.0f,-282.0f,1558.0f,3469.0f,4923.0f,5830.0f,6641.0f,6987.0f, 6529.0f,6087.0f,5244.0f,3590.0f,2216.0f,867.0f,-828.0f,-1832.0f, -2185.0f,-2490.0f,-2024.0f,-932.0f,0.0f,1019.0f,1790.0f,1823.0f, 1405.0f,40.0f,-1920.0f,-3671.0f,-5518.0f,-6787.0f,-6803.0f,-6257.0f, -5205.0f,-3582.0f,-1992.0f,-402.0f,1108.0f,2562.0f,4079.0f,5445.0f, 6714.0f,7629.0f,7854.0f,7469.0f,6328.0f,4577.0f,2361.0f,-129.0f, -2410.0f,-4329.0f,-5863.0f,-6811.0f,-7381.0f,-7646.0f,-7566.0f,-7140.0f, -6209.0f,-4932.0f,-3366.0f,-1326.0f,875.0f,2955.0f,4698.0f,5782.0f, 6425.0f,7083.0f,7396.0f,6802.0f,5686.0f,4393.0f,2899.0f,1156.0f, -643.0f,-2306.0f,-3663.0f,-4345.0f,-3888.0f,-2651.0f,-667.0f,1839.0f, 3437.0f,4353.0f,4377.0f,2650.0f,771.0f,-820.0f,-2908.0f,-4137.0f, -4538.0f,-5373.0f,-5863.0f,-6056.0f,-6209.0f,-5430.0f,-3936.0f,-1703.0f, 1413.0f,4104.0f,5895.0f,7292.0f,7718.0f,7196.0f,6890.0f,6360.0f, 5204.0f,3975.0f,2176.0f,-362.0f,-3109.0f,-5695.0f,-7695.0f,-8819.0f, -9028.0f,-8482.0f,-7510.0f,-6353.0f,-5012.0f,-3406.0f,-1526.0f,586.0f, 2931.0f,5115.0f,6834.0f,8015.0f,8416.0f,8103.0f,7172.0f,5822.0f, 4280.0f,2489.0f,835.0f,-482.0f,-1671.0f,-2233.0f,-1840.0f,-868.0f, 433.0f,1967.0f,2730.0f,2337.0f,1485.0f,200.0f,-1165.0f,-1976.0f, -2482.0f,-3334.0f,-4305.0f,-5325.0f,-6426.0f,-6988.0f,-6506.0f,-5149.0f, -3277.0f,-972.0f,1405.0f,3533.0f,5413.0f,7051.0f,8200.0f,8681.0f, 8601.0f,7782.0f,6095.0f,3814.0f,1044.0f,-1952.0f,-4635.0f,-6779.0f, -8257.0f,-8907.0f,-8923.0f,-8441.0f,-7446.0f,-6000.0f,-3920.0f,-1663.0f, 682.0f,3180.0f,5115.0f,6658.0f,7959.0f,8376.0f,8047.0f,7188.0f, 5541.0f,3324.0f,1276.0f,-611.0f,-2378.0f,-3550.0f,-4016.0f,-3888.0f, -3012.0f,-1141.0f,1204.0f,3067.0f,4385.0f,4947.0f,3991.0f,2570.0f, 1100.0f,-691.0f,-2057.0f,-3077.0f,-4088.0f,-5036.0f,-6056.0f,-6731.0f, -6980.0f,-6530.0f,-4916.0f,-2659.0f,104.0f,2955.0f,5115.0f,6561.0f, 7284.0f,7445.0f,7228.0f,6433.0f,5268.0f,3461.0f,1108.0f,-1197.0f, -3526.0f,-5606.0f,-6835.0f,-7502.0f,-7598.0f,-6964.0f,-5751.0f,-4297.0f, -2860.0f,-1213.0f,361.0f,1501.0f,2762.0f,4120.0f,4883.0f,5413.0f, 5862.0f,5557.0f,4722.0f,3726.0f,2280.0f,730.0f,-587.0f,-1510.0f, -1751.0f,-1607.0f,-1253.0f,-209.0f,939.0f,1678.0f,2802.0f,3702.0f, 3092.0f,2192.0f,875.0f,-1816.0f,-4105.0f,-5558.0f,-7084.0f,-7405.0f, -6618.0f,-6008.0f,-4667.0f,-3052.0f,-1808.0f,24.0f,1919.0f,3421.0f, 5292.0f,6842.0f,7597.0f,8031.0f,7637.0f,6184.0f,4481.0f,2305.0f, -233.0f,-2362.0f,-4297.0f,-6153.0f,-7269.0f,-7919.0f,-8209.0f,-7574.0f, -6418.0f,-5028.0f,-3060.0f,-1085.0f,690.0f,2794.0f,4353.0f,5156.0f, 5999.0f,6240.0f,5686.0f,5196.0f,4385.0f,2907.0f,1397.0f,-121.0f, -1896.0f,-3165.0f,-3888.0f,-3864.0f,-2362.0f,-258.0f,2192.0f,4850.0f, 6160.0f,6144.0f,5421.0f,3164.0f,48.0f,-2530.0f,-4859.0f,-6594.0f, -7462.0f,-7823.0f,-7976.0f,-8088.0f,-7389.0f,-5992.0f,-4273.0f,-1494.0f, 1517.0f,3895.0f,5999.0f,7637.0f,8320.0f,8183.0f,7637.0f,6392.0f, 4577.0f,2409.0f,-378.0f,-3317.0f,-5855.0f,-7911.0f,-9028.0f,-9084.0f, -8562.0f,-7381.0f,-5823.0f,-4362.0f,-2659.0f,-707.0f,1044.0f,3011.0f, 5124.0f,6561.0f,7340.0f,7412.0f,6625.0f,5573.0f,4168.0f,2586.0f, 1276.0f,-145.0f,-1502.0f,-2241.0f,-2121.0f,-828.0f,1293.0f,3726.0f, 5822.0f,6200.0f,5316.0f,3710.0f,1188.0f,-828.0f,-2378.0f,-3856.0f, -5004.0f,-6305.0f,-7654.0f,-8731.0f,-8851.0f,-7927.0f,-6273.0f,-3502.0f, -378.0f,2465.0f,4963.0f,6850.0f,8175.0f,8762.0f,8641.0f,7943.0f, 6561.0f,4553.0f,1823.0f,-1181.0f,-3984.0f,-6450.0f,-8104.0f,-8835.0f, -8827.0f,-8257.0f,-7333.0f,-5887.0f,-4185.0f,-2233.0f,112.0f,2409.0f, 4369.0f,6007.0f,7115.0f,7589.0f,7669.0f,7011.0f,5886.0f,4561.0f, 2714.0f,1148.0f,-258.0f,-1856.0f,-2619.0f,-2386.0f,-1518.0f,224.0f, 2610.0f,4537.0f,4995.0f,4577.0f,3349.0f,690.0f,-1615.0f,-2787.0f, -4281.0f,-5382.0f,-5639.0f,-6506.0f,-7518.0f,-7646.0f,-7164.0f,-5968.0f, -3807.0f,-884.0f,2208.0f,4618.0f,6320.0f,7549.0f,7589.0f,7035.0f, 6842.0f,5991.0f,4409.0f,2835.0f,706.0f,-1896.0f,-4056.0f,-5671.0f, -6875.0f,-7397.0f,-7156.0f,-6514.0f,-5639.0f,-4546.0f,-3317.0f,-1992.0f, -707.0f,971.0f,2802.0f,4465.0f,5830.0f,6513.0f,6392.0f,5621.0f, 4385.0f,2899.0f,1517.0f,136.0f,-1101.0f,-1727.0f,-1920.0f,-1719.0f, -651.0f,923.0f,2288.0f,3461.0f,4344.0f,4208.0f,3019.0f,1453.0f, -659.0f,-3165.0f,-4948.0f,-6088.0f,-7100.0f,-7317.0f,-6867.0f,-6538.0f, -5855.0f,-4442.0f,-2715.0f,-563.0f,1991.0f,4465.0f,6577.0f,8167.0f, 9011.0f,8971.0f,8007.0f,6360.0f,4272.0f,1702.0f,-988.0f,-3430.0f, -5711.0f,-7438.0f,-8369.0f,-8634.0f,-8000.0f,-6691.0f,-5084.0f,-3036.0f, -916.0f,754.0f,2618.0f,4336.0f,5083.0f,5766.0f,6143.0f,5413.0f, 4401.0f,3493.0f,2136.0f,481.0f,-932.0f,-2322.0f,-3430.0f,-3663.0f, -2996.0f,-1318.0f,1108.0f,3598.0f,5646.0f,6746.0f,6449.0f,5011.0f, 2690.0f,-97.0f,-2747.0f,-4851.0f,-6169.0f,-7197.0f,-7614.0f,-7847.0f, -8000.0f,-7100.0f,-5711.0f,-3671.0f,-466.0f,2722.0f,5348.0f,7565.0f, 8609.0f,8505.0f,8191.0f,7212.0f,5734.0f,4208.0f,2007.0f,-755.0f, -3325.0f,-5711.0f,-7606.0f,-8490.0f,-8530.0f,-8016.0f,-6883.0f,-5558.0f, -4329.0f,-2691.0f,-940.0f,771.0f,2899.0f,4698.0f,5991.0f,6995.0f, 7019.0f,6489.0f,5814.0f,4385.0f,2682.0f,1019.0f,-691.0f,-1791.0f, -1920.0f,-1197.0f,481.0f,2586.0f,4553.0f,5766.0f,5597.0f,4385.0f, 2313.0f,-57.0f,-1783.0f,-3052.0f,-4161.0f,-5341.0f,-6771.0f,-8160.0f, -8923.0f,-8642.0f,-7454.0f,-5261.0f,-2402.0f,168.0f,2714.0f,4891.0f, 6368.0f,7613.0f,8208.0f,8208.0f,7589.0f,6168.0f,4176.0f,1558.0f, -1149.0f,-3719.0f,-6032.0f,-7542.0f,-8353.0f,-8658.0f,-8450.0f,-7719.0f, -6594.0f,-4980.0f,-2811.0f,-458.0f,2007.0f,4449.0f,6320.0f,7629.0f, 8360.0f,8256.0f,7613.0f,6441.0f,4714.0f,2931.0f,1100.0f,-595.0f, -2000.0f,-2844.0f,-2828.0f,-2137.0f,-820.0f,979.0f,2296.0f,2553.0f, 2441.0f,1895.0f,473.0f,-362.0f,-426.0f,-1326.0f,-2265.0f,-2900.0f, -4570.0f,-6265.0f,-6691.0f,-6506.0f,-5687.0f,-3888.0f,-1775.0f,216.0f, 1710.0f,2963.0f,4312.0f,5091.0f,5493.0f,6184.0f,6272.0f,5107.0f, 3630.0f,2007.0f,-370.0f,-2490.0f,-3719.0f,-4916.0f,-5839.0f,-6209.0f, -6434.0f,-6418.0f,-6056.0f,-4980.0f,-3366.0f,-1583.0f,393.0f,2417.0f, 3903.0f,4850.0f,5694.0f,5895.0f,5429.0f,4858.0f,3967.0f,2537.0f, 1092.0f,-217.0f,-1181.0f,-1679.0f,-1671.0f,-723.0f,497.0f,1268.0f, 1991.0f,2473.0f,1871.0f,1011.0f,642.0f,-129.0f,-852.0f,-932.0f, -1551.0f,-2579.0f,-3470.0f,-4386.0f,-5181.0f,-5590.0f,-5060.0f,-3751.0f, -2354.0f,-523.0f,1469.0f,2810.0f,3806.0f,4850.0f,5549.0f,5878.0f, 6063.0f,5525.0f,4176.0f,2489.0f,337.0f,-1800.0f,-3550.0f,-5149.0f, -6185.0f,-6602.0f,-6675.0f,-6201.0f,-5277.0f,-4257.0f,-2892.0f,-1189.0f, 698.0f,2682.0f,4200.0f,5156.0f,5638.0f,5509.0f,4858.0f,4168.0f, 3525.0f,2465.0f,1172.0f,-193.0f,-1406.0f,-2065.0f,-2161.0f,-1390.0f, 120.0f,1807.0f,3212.0f,4457.0f,5075.0f,4425.0f,3196.0f,1405.0f, -1157.0f,-3566.0f,-5365.0f,-6867.0f,-7727.0f,-7735.0f,-7389.0f,-6699.0f, -5341.0f,-3422.0f,-1245.0f,1148.0f,3670.0f,6143.0f,8007.0f,9067.0f, 9444.0f,8802.0f,7276.0f,5196.0f,2626.0f,-65.0f,-2828.0f,-5373.0f, -7494.0f,-8923.0f,-9325.0f,-8891.0f,-7735.0f,-6064.0f,-4105.0f,-1952.0f, 425.0f,2586.0f,4128.0f,5348.0f,6264.0f,6915.0f,6866.0f,6264.0f, 5782.0f,4481.0f,2393.0f,650.0f,-868.0f,-2289.0f,-3052.0f,-2603.0f, -1205.0f,489.0f,2586.0f,4706.0f,5846.0f,5694.0f,4810.0f,2875.0f, 128.0f,-1864.0f,-3727.0f,-5647.0f,-6699.0f,-7646.0f,-8313.0f,-8337.0f, -7751.0f,-6402.0f,-4602.0f,-1928.0f,1397.0f,4224.0f,6176.0f,7661.0f, 8352.0f,7886.0f,7083.0f,5967.0f,4095.0f,1847.0f,-852.0f,-3735.0f, -6329.0f,-8369.0f,-9196.0f,-8707.0f,-7606.0f,-6120.0f,-3968.0f,-1888.0f, -177.0f,1582.0f,3260.0f,4561.0f,5678.0f,6497.0f,6641.0f,6376.0f, 5565.0f,4015.0f,2650.0f,1156.0f,-916.0f,-2490.0f,-3470.0f,-3984.0f, -3285.0f,-1462.0f,939.0f,3381.0f,5292.0f,6143.0f,5629.0f,4200.0f, 2240.0f,497.0f,-699.0f,-1912.0f,-3591.0f,-5502.0f,-6988.0f,-8393.0f, -9060.0f,-8064.0f,-6369.0f,-4161.0f,-1358.0f,1108.0f,3043.0f,4867.0f, 6433.0f,7445.0f,7934.0f,7846.0f,7155.0f,5621.0f,3156.0f,337.0f, -2338.0f,-4803.0f,-6482.0f,-7197.0f,-7606.0f,-7574.0f,-7156.0f,-6490.0f, -4996.0f,-3093.0f,-1406.0f,409.0f,2586.0f,4473.0f,5774.0f,6826.0f, 7115.0f,6449.0f,5252.0f,3606.0f,1919.0f,232.0f,-1478.0f,-2803.0f, -3558.0f,-3631.0f,-2860.0f,-1374.0f,690.0f,2602.0f,3172.0f,3204.0f, 2995.0f,1879.0f,1301.0f,971.0f,-611.0f,-2273.0f,-3382.0f,-4868.0f, -6426.0f,-6755.0f,-6313.0f,-5269.0f,-3446.0f,-1711.0f,289.0f,1919.0f, 3100.0f,4529.0f,5477.0f,6039.0f,6304.0f,5686.0f,4361.0f,2401.0f, -298.0f,-2988.0f,-4707.0f,-5839.0f,-6538.0f,-6578.0f,-6426.0f,-5936.0f, -5213.0f,-4209.0f,-2675.0f,-868.0f,955.0f,2859.0f,4457.0f,5276.0f, 5726.0f,5670.0f,5003.0f,4385.0f,3324.0f,1807.0f,658.0f,-298.0f, -1061.0f,-1101.0f,-386.0f,497.0f,1742.0f,3445.0f,3879.0f,3284.0f, 2602.0f,1212.0f,-747.0f,-2402.0f,-3655.0f,-4908.0f,-5920.0f,-6353.0f, -6506.0f,-6434.0f,-5847.0f,-4490.0f,-2659.0f,-659.0f,1566.0f,3590.0f, 5316.0f,6762.0f,7565.0f,7782.0f,7541.0f,6529.0f,4794.0f,2674.0f, -89.0f,-3085.0f,-5598.0f,-7542.0f,-8586.0f,-8931.0f,-8498.0f,-7430.0f, -6064.0f,-4153.0f,-1808.0f,730.0f,3108.0f,5340.0f,7115.0f,7822.0f, 8047.0f,7541.0f,6489.0f,5646.0f,4224.0f,2465.0f,787.0f,-1189.0f, -3157.0f,-4506.0f,-4908.0f,-4450.0f,-2916.0f,-820.0f,1132.0f,2955.0f, 3750.0f,3421.0f,3011.0f,2031.0f,248.0f,-1077.0f,-1944.0f,-3245.0f, -4281.0f,-4819.0f,-5582.0f,-5944.0f,-5422.0f,-4265.0f,-2506.0f,-338.0f, 1935.0f,3855.0f,5268.0f,6232.0f,6682.0f,6593.0f,6063.0f,5364.0f, 4208.0f,2545.0f,626.0f,-1848.0f,-4145.0f,-5871.0f,-7325.0f,-7984.0f, -8048.0f,-7462.0f,-6016.0f,-4321.0f,-2209.0f,401.0f,2802.0f,4690.0f, 6425.0f,7332.0f,7099.0f,6818.0f,6071.0f,4939.0f,3638.0f,1630.0f, -466.0f,-2434.0f,-4249.0f,-5076.0f,-4362.0f,-2619.0f,-314.0f,2610.0f, 4505.0f,4883.0f,5276.0f,4529.0f,2923.0f,2248.0f,1276.0f,-788.0f, -2771.0f,-5044.0f,-7727.0f,-9325.0f,-9397.0f,-8795.0f,-7293.0f,-4763.0f, -2193.0f,168.0f,2385.0f,4706.0f,6754.0f,8264.0f,9091.0f,8898.0f, 7902.0f,6047.0f,3742.0f,1003.0f,-1896.0f,-4362.0f,-6618.0f,-8016.0f, -8755.0f,-9012.0f,-8217.0f,-6932.0f,-5084.0f,-2538.0f,56.0f,2545.0f, 4947.0f,6497.0f,7188.0f,7677.0f,7710.0f,7212.0f,6376.0f,4867.0f, 2859.0f,867.0f,-1334.0f,-3101.0f,-4096.0f,-4418.0f,-3213.0f,-1012.0f, 1260.0f,3726.0f,5107.0f,4537.0f,3742.0f,2618.0f,955.0f,473.0f, -89.0f,-2161.0f,-4370.0f,-6297.0f,-8441.0f,-9397.0f,-8466.0f,-7229.0f, -5197.0f,-2137.0f,449.0f,2883.0f,5356.0f,6987.0f,7822.0f,8344.0f, 7854.0f,6666.0f,5140.0f,2891.0f,248.0f,-2458.0f,-5044.0f,-6907.0f, -8008.0f,-8755.0f,-8875.0f,-8184.0f,-7164.0f,-5590.0f,-3309.0f,-796.0f, 1646.0f,4079.0f,6119.0f,7461.0f,8256.0f,8224.0f,7493.0f,6087.0f, 4224.0f,2433.0f,457.0f,-1551.0f,-3165.0f,-4474.0f,-5125.0f,-4233.0f, -2627.0f,-860.0f,1622.0f,3333.0f,3694.0f,4039.0f,3180.0f,1333.0f, 682.0f,-137.0f,-1430.0f,-1808.0f,-2546.0f,-4032.0f,-5181.0f,-6040.0f, -6570.0f,-6088.0f,-4522.0f,-2314.0f,377.0f,2313.0f,3782.0f,5188.0f, 5332.0f,5236.0f,5188.0f,4096.0f,2690.0f,1220.0f,-812.0f,-2723.0f, -4153.0f,-5269.0f,-5839.0f,-5896.0f,-5671.0f,-5108.0f,-4321.0f,-3446.0f, -2145.0f,-659.0f,666.0f,2112.0f,3204.0f,3935.0f,4786.0f,5156.0f, 5188.0f,4794.0f,3871.0f,2955.0f,1662.0f,192.0f,-1037.0f,-2089.0f, -2338.0f,-2000.0f,-1029.0f,546.0f,1991.0f,2955.0f,3389.0f,3349.0f, 2513.0f,1293.0f,152.0f,-1366.0f,-2948.0f,-4105.0f,-5068.0f,-5687.0f, -5855.0f,-5687.0f,-5285.0f,-4418.0f,-3117.0f,-1518.0f,473.0f,2594.0f, 4521.0f,6039.0f,7067.0f,7461.0f,7027.0f,5870.0f,4079.0f,1871.0f, -450.0f,-2747.0f,-4739.0f,-6385.0f,-7582.0f,-8008.0f,-7622.0f,-6594.0f, -4940.0f,-2828.0f,-595.0f,1590.0f,3549.0f,4923.0f,5316.0f,5878.0f, 6352.0f,5646.0f,5124.0f,4577.0f,3092.0f,1373.0f,-418.0f,-2442.0f, -4169.0f,-5028.0f,-4900.0f,-3470.0f,-924.0f,1815.0f,4433.0f,6184.0f, 6457.0f,5782.0f,3959.0f,1325.0f,-876.0f,-2956.0f,-4691.0f,-5430.0f, -6064.0f,-6907.0f,-7446.0f,-7349.0f,-6699.0f,-5333.0f,-2876.0f,265.0f, 3212.0f,5621.0f,7573.0f,8232.0f,7645.0f,6778.0f,5621.0f,4095.0f, 2497.0f,698.0f,-1695.0f,-4000.0f,-5968.0f,-7614.0f,-8217.0f,-8008.0f, -6835.0f,-5068.0f,-3438.0f,-1510.0f,353.0f,1871.0f,3333.0f,4690.0f, 5533.0f,5734.0f,5742.0f,5236.0f,4288.0f,3316.0f,2015.0f,626.0f, -707.0f,-1800.0f,-2346.0f,-2057.0f,-627.0f,1437.0f,3702.0f,5662.0f, 6256.0f,5694.0f,4264.0f,2152.0f,650.0f,-691.0f,-2362.0f,-3607.0f, -5398.0f,-7558.0f,-8763.0f,-9172.0f,-8715.0f,-7245.0f,-4884.0f,-2346.0f, 56.0f,2634.0f,4698.0f,6192.0f,7734.0f,8384.0f,8192.0f,7557.0f, 6015.0f,3758.0f,1381.0f,-1012.0f,-3334.0f,-5020.0f,-6225.0f,-7229.0f, -7703.0f,-7855.0f,-7614.0f,-6514.0f,-4924.0f,-2820.0f,-217.0f,2280.0f, 4433.0f,6152.0f,7252.0f,7541.0f,7356.0f,6834.0f,5686.0f,4288.0f, 2738.0f,923.0f,-595.0f,-1133.0f,-972.0f,-426.0f,971.0f,1991.0f, 1429.0f,658.0f,-137.0f,-1896.0f,-2683.0f,-2233.0f,-2868.0f,-3470.0f, -3767.0f,-5092.0f,-5928.0f,-5711.0f,-5060.0f,-3647.0f,-2097.0f,-884.0f, 497.0f,1670.0f,3172.0f,5083.0f,6360.0f,7276.0f,7862.0f,7188.0f, 5726.0f,4128.0f,1413.0f,-1543.0f,-3823.0f,-5815.0f,-7181.0f,-7735.0f, -8048.0f,-8176.0f,-7687.0f,-6659.0f,-5044.0f,-2908.0f,-739.0f,1445.0f, 3718.0f,5605.0f,7196.0f,8497.0f,8810.0f,8175.0f,6818.0f,4738.0f, 2642.0f,706.0f,-1647.0f,-3510.0f,-4594.0f,-5470.0f,-5197.0f,-3582.0f, -2016.0f,-563.0f,1373.0f,2280.0f,2537.0f,3003.0f,2778.0f,2465.0f, 1887.0f,449.0f,-1350.0f,-3068.0f,-4570.0f,-5213.0f,-5012.0f,-4490.0f, -3004.0f,-1382.0f,-362.0f,955.0f,1790.0f,2023.0f,3067.0f,4208.0f, 4537.0f,4778.0f,4513.0f,2971.0f,1188.0f,-595.0f,-2755.0f,-4297.0f, -5317.0f,-6064.0f,-6056.0f,-5791.0f,-5116.0f,-3799.0f,-2081.0f,-97.0f, 2240.0f,4176.0f,5453.0f,6256.0f,5911.0f,5212.0f,4521.0f,3124.0f, 1646.0f,216.0f,-1783.0f,-3342.0f,-3984.0f,-4297.0f,-3550.0f,-1992.0f, -723.0f,1276.0f,3525.0f,4818.0f,6143.0f,7003.0f,6915.0f,6280.0f, 4987.0f,3059.0f,385.0f,-2209.0f,-4715.0f,-7068.0f,-8361.0f,-9245.0f, -9405.0f,-8530.0f,-7317.0f,-5454.0f,-2972.0f,-41.0f,2907.0f,5662.0f, 7943.0f,9115.0f,9485.0f,9099.0f,7878.0f,6160.0f,4023.0f,1533.0f, -956.0f,-3285.0f,-5534.0f,-7269.0f,-8184.0f,-8297.0f,-7807.0f,-6667.0f, -5004.0f,-3518.0f,-1872.0f,40.0f,1309.0f,2353.0f,3622.0f,4505.0f, 4915.0f,5220.0f,5597.0f,4802.0f,3268.0f,2497.0f,1188.0f,-57.0f, 281.0f,1196.0f,2618.0f,4585.0f,6232.0f,6433.0f,5670.0f,4585.0f, 2537.0f,345.0f,-1960.0f,-4241.0f,-6193.0f,-7968.0f,-9188.0f,-9839.0f, -9622.0f,-8586.0f,-7116.0f,-5141.0f,-2667.0f,96.0f,3124.0f,5533.0f, 7437.0f,8794.0f,9019.0f,8497.0f,7493.0f,5935.0f,3967.0f,1935.0f, -563.0f,-3301.0f,-5896.0f,-8152.0f,-9277.0f,-9678.0f,-9494.0f,-8345.0f, -7012.0f,-5502.0f,-3510.0f,-1398.0f,867.0f,3284.0f,5381.0f,7244.0f, 8408.0f,8577.0f,8529.0f,7894.0f,6208.0f,4377.0f,2473.0f,714.0f, -571.0f,-908.0f,-233.0f,762.0f,2096.0f,3196.0f,3148.0f,2128.0f, 401.0f,-1912.0f,-3687.0f,-4956.0f,-5655.0f,-6072.0f,-7036.0f,-7839.0f, -8016.0f,-7719.0f,-6506.0f,-4643.0f,-2659.0f,-249.0f,2048.0f,4272.0f, 5983.0f,6939.0f,7894.0f,7702.0f,6834.0f,6007.0f,4144.0f,2256.0f, 192.0f,-2603.0f,-5068.0f,-7197.0f,-8787.0f,-9156.0f,-8851.0f,-7863.0f, -6474.0f,-5028.0f,-3052.0f,-1125.0f,1084.0f,3614.0f,5822.0f,7501.0f, 8946.0f,9420.0f,8786.0f,7782.0f,6087.0f,4071.0f,1847.0f,-346.0f, -2209.0f,-3767.0f,-4362.0f,-4048.0f,-3181.0f,-1671.0f,-643.0f,-988.0f, -916.0f,-1245.0f,-2587.0f,-2434.0f,-1928.0f,-2530.0f,-2635.0f,-3117.0f, -4619.0f,-5309.0f,-5084.0f,-4113.0f,-2177.0f,168.0f,2256.0f,4353.0f, 5742.0f,6433.0f,7404.0f,7260.0f,6473.0f,5694.0f,4007.0f,1790.0f, -515.0f,-3229.0f,-5695.0f,-7662.0f,-8819.0f,-8739.0f,-8321.0f,-7389.0f, -5863.0f,-4386.0f,-2458.0f,-89.0f,2369.0f,4650.0f,6481.0f,8256.0f, 8938.0f,8577.0f,8304.0f,7252.0f,5573.0f,3750.0f,1469.0f,-1109.0f, -3462.0f,-5141.0f,-5879.0f,-5727.0f,-4892.0f,-3077.0f,-1229.0f,-73.0f, 1341.0f,1943.0f,1389.0f,1140.0f,939.0f,441.0f,369.0f,96.0f, -852.0f,-1864.0f,-3004.0f,-4064.0f,-4442.0f,-3960.0f,-2643.0f,-587.0f, 1301.0f,2867.0f,4288.0f,4875.0f,5011.0f,5292.0f,5003.0f,4047.0f, 2979.0f,1301.0f,-988.0f,-3350.0f,-5598.0f,-7237.0f,-8048.0f,-7911.0f, -6803.0f,-5125.0f,-3173.0f,-1221.0f,1019.0f,3413.0f,5075.0f,6529.0f, 7653.0f,7581.0f,6730.0f,5525.0f,3967.0f,2112.0f,530.0f,-924.0f, -2498.0f,-3759.0f,-4884.0f,-5695.0f,-5622.0f,-4827.0f,-3542.0f,-1502.0f, 939.0f,2979.0f,4810.0f,6176.0f,6328.0f,5766.0f,4754.0f,3076.0f, 1100.0f,-884.0f,-2884.0f,-4683.0f,-6104.0f,-7004.0f,-7156.0f,-6739.0f, -5936.0f,-4370.0f,-2322.0f,-233.0f,2104.0f,4409.0f,6023.0f,7019.0f, 7364.0f,6762.0f,5348.0f,3549.0f,1533.0f,-683.0f,-2595.0f,-3856.0f, -4843.0f,-5357.0f,-5012.0f,-4442.0f,-3944.0f,-3004.0f,-1800.0f,-844.0f, 176.0f,1397.0f,2513.0f,3300.0f,3871.0f,4272.0f,4256.0f,3766.0f, 2939.0f,1847.0f,385.0f,-1286.0f,-2659.0f,-3398.0f,-3133.0f,-1695.0f, 530.0f,3043.0f,5027.0f,5959.0f,6111.0f,5389.0f,3838.0f,2385.0f, 1212.0f,-354.0f,-2161.0f,-4096.0f,-6281.0f,-8233.0f,-9229.0f,-9044.0f, -8225.0f,-6586.0f,-4209.0f,-2137.0f,-362.0f,1533.0f,3525.0f,5284.0f, 6746.0f,8047.0f,8497.0f,7822.0f,6770.0f,5075.0f,2786.0f,706.0f, -1093.0f,-3036.0f,-4964.0f,-6177.0f,-7189.0f,-7984.0f,-7887.0f,-6907.0f, -5550.0f,-3695.0f,-1213.0f,1003.0f,3019.0f,4706.0f,5718.0f,6409.0f, 6577.0f,6063.0f,5132.0f,3871.0f,2152.0f,738.0f,-209.0f,-683.0f, 64.0f,1140.0f,2248.0f,3662.0f,3879.0f,2995.0f,1839.0f,192.0f, -1318.0f,-2065.0f,-2554.0f,-3591.0f,-5044.0f,-6418.0f,-7606.0f,-8241.0f, -7678.0f,-6289.0f,-4498.0f,-2683.0f,-1165.0f,554.0f,2048.0f,3790.0f, 5886.0f,7493.0f,8569.0f,8794.0f,8079.0f,6834.0f,5075.0f,3108.0f, 819.0f,-1751.0f,-3848.0f,-6000.0f,-7927.0f,-8610.0f,-8707.0f,-8249.0f, -6956.0f,-5277.0f,-3325.0f,-1261.0f,811.0f,2963.0f,4995.0f,6457.0f, 7380.0f,7621.0f,7115.0f,6095.0f,4714.0f,3228.0f,1742.0f,457.0f, -563.0f,-1133.0f,-1446.0f,-1607.0f,-1374.0f,-1848.0f,-2322.0f,-2346.0f, -2916.0f,-2755.0f,-1968.0f,-1687.0f,-1374.0f,-1534.0f,-2241.0f,-3101.0f, -4032.0f,-4097.0f,-3751.0f,-3510.0f,-2530.0f,-1438.0f,-820.0f,120.0f, 1903.0f,3774.0f,5172.0f,6641.0f,7429.0f,6890.0f,5895.0f,4312.0f, 1999.0f,-394.0f,-2579.0f,-4619.0f,-6329.0f,-7245.0f,-7542.0f,-7719.0f, -7164.0f,-5783.0f,-4185.0f,-2306.0f,-241.0f,1726.0f,3220.0f,4200.0f, 5397.0f,5830.0f,5469.0f,5276.0f,5188.0f,4698.0f,3469.0f,2039.0f, 417.0f,-1261.0f,-2362.0f,-2924.0f,-2820.0f,-1767.0f,-739.0f,-161.0f, 714.0f,1028.0f,265.0f,72.0f,8.0f,-956.0f,-1743.0f,-2514.0f, -3872.0f,-5261.0f,-6193.0f,-6177.0f,-5534.0f,-4426.0f,-2225.0f,457.0f, 2714.0f,4601.0f,6593.0f,7348.0f,6866.0f,6955.0f,6328.0f,4834.0f, 3501.0f,1598.0f,-796.0f,-2731.0f,-4562.0f,-6032.0f,-6683.0f,-7221.0f, -7285.0f,-6554.0f,-5558.0f,-4281.0f,-2394.0f,-362.0f,1525.0f,3790.0f, 5846.0f,7228.0f,8135.0f,8352.0f,7814.0f,6601.0f,5115.0f,3324.0f, 1164.0f,-860.0f,-2506.0f,-3775.0f,-4482.0f,-4097.0f,-2916.0f,-1350.0f, 570.0f,2240.0f,3533.0f,3943.0f,2987.0f,1525.0f,8.0f,-1631.0f, -2988.0f,-4209.0f,-5301.0f,-5912.0f,-5968.0f,-5566.0f,-4619.0f,-3036.0f, -1004.0f,1509.0f,3734.0f,5300.0f,6666.0f,7075.0f,6698.0f,6200.0f, 5445.0f,4296.0f,2843.0f,1100.0f,-1069.0f,-3253.0f,-5406.0f,-7229.0f, -8176.0f,-8530.0f,-8273.0f,-7189.0f,-5647.0f,-3848.0f,-1567.0f,851.0f, 3084.0f,5340.0f,6987.0f,7951.0f,8216.0f,7437.0f,6192.0f,4377.0f, 2337.0f,514.0f,-1567.0f,-3325.0f,-3984.0f,-3727.0f,-2418.0f,-97.0f, 2505.0f,4658.0f,5613.0f,5517.0f,4545.0f,2891.0f,1116.0f,-386.0f, -1735.0f,-3486.0f,-5277.0f,-6924.0f,-8040.0f,-7944.0f,-7084.0f,-5373.0f, -2763.0f,32.0f,2015.0f,3156.0f,4449.0f,5188.0f,6047.0f,7252.0f, 7260.0f,6505.0f,5429.0f,3654.0f,1646.0f,-555.0f,-3052.0f,-5229.0f, -6859.0f,-7807.0f,-8160.0f,-7935.0f,-7213.0f,-5984.0f,-4378.0f,-2394.0f, -1.0f,2441.0f,4738.0f,6449.0f,7637.0f,8127.0f,7959.0f,7284.0f, 6111.0f,4473.0f,2409.0f,313.0f,-1446.0f,-2795.0f,-3438.0f,-2787.0f, -1149.0f,762.0f,2851.0f,4055.0f,3525.0f,2160.0f,433.0f,-1382.0f, -2611.0f,-2868.0f,-3157.0f,-4297.0f,-5092.0f,-5647.0f,-6305.0f,-5606.0f, -3655.0f,-1783.0f,56.0f,1606.0f,3019.0f,3590.0f,3766.0f,4794.0f, 5557.0f,6160.0f,6585.0f,6184.0f,4923.0f,2995.0f,947.0f,-1294.0f, -3542.0f,-5622.0f,-7116.0f,-7984.0f,-8538.0f,-8120.0f,-7148.0f,-5896.0f, -3984.0f,-1880.0f,449.0f,2963.0f,5003.0f,6754.0f,7686.0f,7445.0f, 7147.0f,6449.0f,4931.0f,3557.0f,2128.0f,112.0f,-1534.0f,-2707.0f, -3141.0f,-2579.0f,-1639.0f,-49.0f,1646.0f,1807.0f,1164.0f,586.0f, -1181.0f,-2554.0f,-2482.0f,-2394.0f,-1856.0f,-1526.0f,-2225.0f,-2972.0f, -3751.0f,-4329.0f,-4000.0f,-2731.0f,-1374.0f,-153.0f,1317.0f,2353.0f, 3092.0f,4304.0f,5180.0f,5943.0f,6738.0f,6192.0f,5164.0f,3967.0f, 1622.0f,-972.0f,-3446.0f,-5727.0f,-7253.0f,-7871.0f,-7703.0f,-7100.0f, -6008.0f,-4562.0f,-2868.0f,-715.0f,1485.0f,3549.0f,5228.0f,6111.0f, 6441.0f,6216.0f,5300.0f,4545.0f,3847.0f,2650.0f,1485.0f,281.0f, -900.0f,-2049.0f,-2643.0f,-2241.0f,-1816.0f,-932.0f,385.0f,819.0f, 1060.0f,1276.0f,714.0f,401.0f,602.0f,425.0f,-73.0f,-161.0f, -274.0f,-1832.0f,-3550.0f,-4370.0f,-5735.0f,-6731.0f,-6032.0f,-4843.0f, -3502.0f,-1149.0f,1252.0f,3300.0f,5413.0f,6746.0f,7396.0f,7477.0f, 6513.0f,5172.0f,3501.0f,1011.0f,-1543.0f,-3663.0f,-5871.0f,-7462.0f, -7582.0f,-7446.0f,-6779.0f,-5293.0f,-3856.0f,-2121.0f,-442.0f,1228.0f, 3116.0f,4449.0f,5324.0f,6119.0f,6184.0f,5421.0f,4634.0f,4023.0f, 2827.0f,1148.0f,-49.0f,-1390.0f,-2932.0f,-3566.0f,-3582.0f,-3093.0f, -2105.0f,-972.0f,433.0f,1887.0f,3164.0f,3927.0f,3847.0f,3485.0f, 2931.0f,1373.0f,-659.0f,-2362.0f,-4458.0f,-6827.0f,-8120.0f,-8128.0f, -7783.0f,-6747.0f,-4675.0f,-2386.0f,144.0f,2674.0f,4698.0f,6633.0f, 7766.0f,7766.0f,7292.0f,6152.0f,4361.0f,2240.0f,-241.0f,-2908.0f, -5060.0f,-6755.0f,-7895.0f,-8112.0f,-7670.0f,-6899.0f,-6040.0f,-4498.0f, -2450.0f,-635.0f,1293.0f,3573.0f,5509.0f,6376.0f,6794.0f,7308.0f, 6842.0f,5477.0f,4296.0f,2754.0f,433.0f,-1647.0f,-3438.0f,-4924.0f, -5189.0f,-4394.0f,-2884.0f,-587.0f,1774.0f,3357.0f,4047.0f,4200.0f, 4618.0f,4320.0f,3124.0f,2449.0f,554.0f,-2579.0f,-5100.0f,-7164.0f, -8369.0f,-8506.0f,-7542.0f,-5984.0f,-4225.0f,-2354.0f,-563.0f,1670.0f, 4007.0f,5509.0f,6489.0f,7115.0f,7011.0f,6280.0f,4810.0f,2907.0f, 979.0f,-940.0f,-2956.0f,-4819.0f,-6104.0f,-7245.0f,-8104.0f,-8192.0f, -7478.0f,-6450.0f,-5004.0f,-2996.0f,-916.0f,1317.0f,3308.0f,5124.0f, 6714.0f,7252.0f,7340.0f,7099.0f,6007.0f,4248.0f,2216.0f,112.0f, -1912.0f,-2980.0f,-2763.0f,-2233.0f,-940.0f,762.0f,1164.0f,971.0f, 1405.0f,1879.0f,1469.0f,1301.0f,1140.0f,-972.0f,-3623.0f,-5438.0f, -7036.0f,-7895.0f,-7060.0f,-5598.0f,-4153.0f,-2297.0f,-434.0f,1445.0f, 3437.0f,5525.0f,7404.0f,8449.0f,8577.0f,8055.0f,6826.0f,5043.0f, 3220.0f,1437.0f,-490.0f,-2659.0f,-4410.0f,-5855.0f,-7333.0f,-8201.0f, -8112.0f,-7454.0f,-6490.0f,-4803.0f,-2876.0f,-940.0f,1212.0f,3236.0f, 5332.0f,6955.0f,7669.0f,8143.0f,7830.0f,6609.0f,4971.0f,2827.0f, 353.0f,-1743.0f,-2755.0f,-3157.0f,-2707.0f,-980.0f,72.0f,497.0f, 1317.0f,1614.0f,1782.0f,2080.0f,2015.0f,1397.0f,-314.0f,-2771.0f, -4948.0f,-6859.0f,-7887.0f,-7229.0f,-5992.0f,-4177.0f,-1767.0f,-193.0f, 891.0f,2369.0f,3847.0f,5051.0f,6569.0f,7790.0f,7710.0f,6898.0f, 5862.0f,4184.0f,2168.0f,232.0f,-1703.0f,-3229.0f,-4819.0f,-6329.0f, -7421.0f,-8217.0f,-8353.0f,-7510.0f,-6096.0f,-4522.0f,-2281.0f,40.0f, 1983.0f,3959.0f,5710.0f,6641.0f,7372.0f,7726.0f,7188.0f,5983.0f, 4031.0f,1702.0f,-442.0f,-2177.0f,-2868.0f,-2386.0f,-1221.0f,505.0f, 2128.0f,2947.0f,3059.0f,2995.0f,2176.0f,706.0f,-314.0f,-1462.0f, -3237.0f,-4811.0f,-6225.0f,-7863.0f,-8313.0f,-7454.0f,-6313.0f,-4474.0f, -2081.0f,104.0f,2353.0f,4593.0f,5991.0f,6842.0f,7509.0f,7404.0f, 7035.0f,6248.0f,4842.0f,3228.0f,1140.0f,-1069.0f,-3173.0f,-5221.0f, -6827.0f,-7735.0f,-8385.0f,-8506.0f,-7863.0f,-6964.0f,-5526.0f,-3647.0f, -1719.0f,481.0f,2690.0f,4915.0f,6939.0f,7886.0f,8320.0f,8208.0f, 7131.0f,5694.0f,3822.0f,1485.0f,-804.0f,-2900.0f,-4281.0f,-4562.0f, -4064.0f,-2579.0f,-378.0f,1228.0f,2505.0f,4023.0f,4120.0f,3035.0f, 2240.0f,803.0f,-1414.0f,-3181.0f,-4562.0f,-6104.0f,-6996.0f,-7156.0f, -7020.0f,-5968.0f,-4586.0f,-3253.0f,-1197.0f,1003.0f,2851.0f,4842.0f, 6489.0f,7147.0f,7525.0f,7493.0f,6465.0f,5397.0f,4095.0f,2208.0f, 337.0f,-1848.0f,-4040.0f,-5960.0f,-7654.0f,-8594.0f,-8923.0f,-8763.0f, -7847.0f,-6321.0f,-4611.0f,-2530.0f,-290.0f,1967.0f,4232.0f,5911.0f, 7147.0f,7629.0f,7236.0f,6232.0f,4449.0f,2570.0f,714.0f,-1221.0f, -2884.0f,-3775.0f,-3526.0f,-2563.0f,-619.0f,1887.0f,3244.0f,4031.0f, 4762.0f,3967.0f,2553.0f,1879.0f,963.0f,-844.0f,-2691.0f,-4321.0f, -6626.0f,-8401.0f,-8506.0f,-7919.0f,-6899.0f,-4803.0f,-2683.0f,-956.0f, 746.0f,2039.0f,3413.0f,5003.0f,6513.0f,7934.0f,8079.0f,7340.0f, 6320.0f,4553.0f,2859.0f,875.0f,-1197.0f,-2940.0f,-4980.0f,-6659.0f, -7855.0f,-8715.0f,-8779.0f,-8008.0f,-6699.0f,-5165.0f,-3060.0f,-964.0f, 827.0f,2714.0f,4505.0f,6200.0f,7324.0f,7686.0f,7453.0f,6537.0f, 4786.0f,2802.0f,642.0f,-1543.0f,-2522.0f,-2498.0f,-1679.0f,265.0f, 2047.0f,3019.0f,3662.0f,3252.0f,2112.0f,1228.0f,433.0f,-563.0f, -1944.0f,-3831.0f,-5944.0f,-7614.0f,-8393.0f,-8000.0f,-6675.0f,-5141.0f, -3430.0f,-1687.0f,377.0f,2192.0f,3670.0f,5710.0f,7324.0f,8336.0f, 8489.0f,7509.0f,6441.0f,5059.0f,3397.0f,1895.0f,48.0f,-2065.0f, -4105.0f,-6201.0f,-8096.0f,-8939.0f,-9020.0f,-8417.0f,-7044.0f,-5478.0f, -3719.0f,-1824.0f,289.0f,2754.0f,4987.0f,6730.0f,8296.0f,8995.0f, 8617.0f,7951.0f,6537.0f,4296.0f,1935.0f,-362.0f,-2032.0f,-2595.0f, -2755.0f,-1936.0f,-266.0f,-145.0f,-217.0f,1036.0f,923.0f,32.0f, 738.0f,787.0f,-1085.0f,-2820.0f,-4193.0f,-6000.0f,-7052.0f,-6570.0f, -5341.0f,-3807.0f,-2113.0f,-804.0f,971.0f,2762.0f,3871.0f,5742.0f, 7324.0f,7710.0f,7967.0f,7477.0f,6232.0f,4979.0f,3236.0f,1349.0f, -506.0f,-2273.0f,-3823.0f,-5614.0f,-7148.0f,-7984.0f,-8305.0f,-7879.0f, -6731.0f,-5261.0f,-3542.0f,-1671.0f,265.0f,2497.0f,4610.0f,6087.0f, 7356.0f,8127.0f,7967.0f,7340.0f,6127.0f,4176.0f,1911.0f,-370.0f, -2113.0f,-2643.0f,-2506.0f,-1800.0f,-105.0f,722.0f,329.0f,1003.0f, 1750.0f,875.0f,674.0f,1180.0f,-153.0f,-2257.0f,-3534.0f,-5084.0f, -6932.0f,-7197.0f,-6305.0f,-5502.0f,-3791.0f,-1543.0f,32.0f,1574.0f, 3043.0f,4336.0f,5734.0f,6513.0f,7099.0f,7453.0f,6449.0f,5228.0f, 4031.0f,2031.0f,112.0f,-1679.0f,-3293.0f,-4771.0f,-6217.0f,-7237.0f, -7735.0f,-7735.0f,-7237.0f,-6032.0f,-4426.0f,-2787.0f,-812.0f,1196.0f, 3212.0f,5107.0f,6392.0f,7461.0f,8143.0f,8071.0f,7268.0f,5927.0f, 4096.0f,1887.0f,-249.0f,-1759.0f,-2442.0f,-2563.0f,-1824.0f,-515.0f, 88.0f,642.0f,1678.0f,1493.0f,546.0f,377.0f,-161.0f,-1438.0f, -2811.0f,-4040.0f,-5269.0f,-6514.0f,-6827.0f,-6048.0f,-5044.0f,-3430.0f, -1101.0f,987.0f,3067.0f,4987.0f,6087.0f,6778.0f,7155.0f,7123.0f, 6521.0f,5501.0f,4473.0f,2827.0f,771.0f,-1229.0f,-3205.0f,-4811.0f, -6265.0f,-7253.0f,-7518.0f,-7606.0f,-7365.0f,-6474.0f,-5181.0f,-3711.0f, -1848.0f,385.0f,2529.0f,4730.0f,6601.0f,7541.0f,8063.0f,8111.0f, 7043.0f,5469.0f,3975.0f,2072.0f,-161.0f,-1984.0f,-2884.0f,-3518.0f, -3783.0f,-2836.0f,-1390.0f,-113.0f,859.0f,1493.0f,2425.0f,2586.0f, 1413.0f,875.0f,489.0f,-1229.0f,-3004.0f,-4040.0f,-5245.0f,-6209.0f, -6144.0f,-5365.0f,-3896.0f,-2073.0f,-386.0f,1542.0f,3308.0f,4417.0f, 5260.0f,5654.0f,5790.0f,5967.0f,5525.0f,4626.0f,3855.0f,2465.0f, 353.0f,-1623.0f,-3237.0f,-4811.0f,-6305.0f,-7269.0f,-7614.0f,-7751.0f, -7430.0f,-6273.0f,-4715.0f,-3004.0f,-972.0f,1011.0f,3164.0f,5220.0f, 6256.0f,7196.0f,7782.0f,7107.0f,5959.0f,4505.0f,2441.0f,88.0f, -2024.0f,-3374.0f,-4016.0f,-4201.0f,-3454.0f,-2081.0f,-1125.0f,-498.0f, 457.0f,1887.0f,2802.0f,2859.0f,3156.0f,2762.0f,530.0f,-1856.0f, -3582.0f,-5253.0f,-6233.0f,-5944.0f,-5068.0f,-3928.0f,-3085.0f,-2667.0f, -1310.0f,345.0f,1839.0f,3863.0f,5445.0f,5718.0f,5284.0f,4730.0f, 4112.0f,3654.0f,3084.0f,2023.0f,634.0f,-836.0f,-2635.0f,-4827.0f, -6578.0f,-7558.0f,-8289.0f,-8522.0f,-7711.0f,-6377.0f,-5028.0f,-3502.0f, -1663.0f,522.0f,2393.0f,3557.0f,5115.0f,6770.0f,7236.0f,6955.0f, 6352.0f,5067.0f,3517.0f,1686.0f,-41.0f,-587.0f,-1085.0f,-1575.0f, -772.0f,-249.0f,-643.0f,-523.0f,144.0f,722.0f,730.0f,369.0f, -611.0f,-2659.0f,-4683.0f,-6273.0f,-7301.0f,-7044.0f,-6112.0f,-5285.0f, -3960.0f,-2378.0f,-1318.0f,232.0f,2851.0f,5180.0f,6738.0f,7918.0f, 8143.0f,7750.0f,6842.0f,5292.0f,4031.0f,2329.0f,136.0f,-1800.0f, -3912.0f,-5904.0f,-7373.0f,-8530.0f,-9124.0f,-8666.0f,-7823.0f,-6675.0f, -4932.0f,-3093.0f,-1318.0f,730.0f,2907.0f,5340.0f,7445.0f,8681.0f, 9380.0f,9300.0f,8449.0f,6947.0f,5180.0f,3300.0f,1028.0f,-852.0f, -1775.0f,-2755.0f,-3494.0f,-3125.0f,-2980.0f,-2651.0f,-1286.0f,-490.0f, 337.0f,1807.0f,1437.0f,240.0f,-595.0f,-2458.0f,-4434.0f,-5125.0f, -5317.0f,-5301.0f,-4418.0f,-3382.0f,-2129.0f,-274.0f,1574.0f,3116.0f, 4834.0f,6360.0f,7380.0f,7951.0f,7653.0f,6537.0f,4955.0f,3196.0f, 1188.0f,-755.0f,-2498.0f,-4602.0f,-6161.0f,-7124.0f,-8128.0f,-8401.0f, -7670.0f,-6691.0f,-5574.0f,-3960.0f,-2225.0f,-458.0f,1566.0f,3493.0f, 5236.0f,6947.0f,7870.0f,8256.0f,8424.0f,7637.0f,6320.0f,4778.0f, 2794.0f,987.0f,-386.0f,-1510.0f,-2065.0f,-2048.0f,-2241.0f,-2498.0f, -1912.0f,-1173.0f,-667.0f,-113.0f,754.0f,1357.0f,465.0f,-699.0f, -1856.0f,-4008.0f,-5799.0f,-6249.0f,-6080.0f,-5341.0f,-3783.0f,-2000.0f, -418.0f,1509.0f,3477.0f,5348.0f,7380.0f,8641.0f,8874.0f,8296.0f, 7123.0f,5437.0f,3429.0f,1268.0f,-1061.0f,-2868.0f,-4362.0f,-5719.0f, -6506.0f,-6907.0f,-6988.0f,-6883.0f,-6201.0f,-4755.0f,-3229.0f,-1775.0f, -169.0f,1293.0f,2337.0f,3397.0f,4634.0f,5838.0f,6754.0f,7043.0f, 6898.0f,6304.0f,5220.0f,3967.0f,2529.0f,931.0f,-354.0f,-1302.0f, -1920.0f,-1599.0f,-1037.0f,-972.0f,-619.0f,-41.0f,-113.0f,-523.0f, -386.0f,0.0f,-571.0f,-1631.0f,-2217.0f,-3398.0f,-5084.0f,-5952.0f, -6144.0f,-5920.0f,-4892.0f,-3197.0f,-1117.0f,1276.0f,3678.0f,5605.0f, 7163.0f,8224.0f,8449.0f,8159.0f,7212.0f,5878.0f,4208.0f,2248.0f, 257.0f,-2137.0f,-4474.0f,-6281.0f,-7727.0f,-8297.0f,-8072.0f,-7646.0f, -7092.0f,-5928.0f,-4362.0f,-2916.0f,-836.0f,1421.0f,3389.0f,5140.0f, 6352.0f,7469.0f,8272.0f,8400.0f,8127.0f,7573.0f,6449.0f,4738.0f, 2939.0f,939.0f,-1294.0f,-3093.0f,-4273.0f,-4803.0f,-4474.0f,-3719.0f, -2739.0f,-1567.0f,-266.0f,706.0f,762.0f,1036.0f,1678.0f,923.0f, -282.0f,-747.0f,-2040.0f,-4000.0f,-5068.0f,-5590.0f,-5783.0f,-4956.0f, -3374.0f,-1374.0f,1052.0f,3389.0f,5276.0f,7027.0f,8071.0f,8087.0f, 7541.0f,6384.0f,4883.0f,3027.0f,971.0f,-1422.0f,-3952.0f,-5815.0f, -7526.0f,-8626.0f,-8482.0f,-8144.0f,-7654.0f,-6385.0f,-4675.0f,-3060.0f, -1117.0f,955.0f,2835.0f,4545.0f,5806.0f,6738.0f,7380.0f,7501.0f, 7003.0f,6304.0f,5397.0f,3855.0f,1879.0f,-9.0f,-1816.0f,-3141.0f, -3727.0f,-4096.0f,-3711.0f,-3125.0f,-3277.0f,-2892.0f,-1743.0f,-619.0f, 248.0f,1807.0f,3132.0f,2200.0f,722.0f,-603.0f,-2836.0f,-4916.0f, -5711.0f,-5349.0f,-5277.0f,-4811.0f,-3566.0f,-2538.0f,-996.0f,1357.0f, 3871.0f,6144.0f,7798.0f,8312.0f,7669.0f,6441.0f,4802.0f,2819.0f, 578.0f,-1896.0f,-3783.0f,-5438.0f,-7197.0f,-7903.0f,-8072.0f,-8168.0f, -7438.0f,-5976.0f,-4145.0f,-2338.0f,-683.0f,899.0f,2264.0f,3373.0f, 4417.0f,5453.0f,6360.0f,6706.0f,6601.0f,6216.0f,5276.0f,4104.0f, 2361.0f,489.0f,-515.0f,-1583.0f,-2675.0f,-2836.0f,-2747.0f,-3775.0f, -4619.0f,-3920.0f,-3189.0f,-2153.0f,-330.0f,650.0f,1164.0f,947.0f, -490.0f,-1567.0f,-2434.0f,-3390.0f,-3936.0f,-4121.0f,-4105.0f,-3550.0f, -2418.0f,-1414.0f,160.0f,2240.0f,3557.0f,4939.0f,6666.0f,6906.0f, 6095.0f,5091.0f,3429.0f,1517.0f,-515.0f,-2811.0f,-4482.0f,-6008.0f, -7301.0f,-7590.0f,-7413.0f,-6787.0f,-5783.0f,-4418.0f,-2771.0f,-1141.0f, 353.0f,1807.0f,3043.0f,4047.0f,4826.0f,5445.0f,6144.0f,6625.0f, 6368.0f,5814.0f,5107.0f,3606.0f,2072.0f,1285.0f,-89.0f,-1470.0f, -1976.0f,-3253.0f,-4611.0f,-4586.0f,-4578.0f,-4345.0f,-2988.0f,-1406.0f, 40.0f,385.0f,481.0f,1469.0f,795.0f,-860.0f,-691.0f,-876.0f, -2675.0f,-3285.0f,-2707.0f,-3004.0f,-2779.0f,-1374.0f,-1.0f,1566.0f, 3164.0f,4465.0f,5670.0f,5895.0f,5565.0f,4923.0f,3284.0f,1823.0f, 200.0f,-2314.0f,-4217.0f,-5767.0f,-7148.0f,-7446.0f,-7181.0f,-6217.0f, -5020.0f,-4064.0f,-2458.0f,-643.0f,843.0f,2345.0f,3549.0f,4618.0f, 5324.0f,5533.0f,5870.0f,6071.0f,5613.0f,4794.0f,3959.0f,3188.0f, 2586.0f,1935.0f,1092.0f,409.0f,-844.0f,-2643.0f,-3438.0f,-3848.0f, -4209.0f,-3703.0f,-2828.0f,-2314.0f,-1438.0f,-804.0f,-1197.0f,-1020.0f, -394.0f,-667.0f,-731.0f,-394.0f,-772.0f,-1534.0f,-1848.0f,-1703.0f, -1149.0f,265.0f,2015.0f,3710.0f,5196.0f,5702.0f,5750.0f,5959.0f, 5260.0f,3991.0f,2650.0f,554.0f,-1703.0f,-3823.0f,-5992.0f,-7421.0f, -8289.0f,-8506.0f,-7727.0f,-6514.0f,-4795.0f,-2811.0f,-1020.0f,811.0f, 2642.0f,4176.0f,5204.0f,5991.0f,6561.0f,6433.0f,5927.0f,5501.0f, 4858.0f,4007.0f,3172.0f,2634.0f,2144.0f,1429.0f,859.0f,192.0f, -1037.0f,-2362.0f,-3446.0f,-4273.0f,-4811.0f,-4651.0f,-3856.0f,-3245.0f, -2739.0f,-1695.0f,-1012.0f,-1382.0f,-1302.0f,-362.0f,313.0f,682.0f, 1421.0f,1533.0f,441.0f,-177.0f,112.0f,361.0f,1220.0f,2778.0f, 3879.0f,4473.0f,4690.0f,4353.0f,3774.0f,2843.0f,1742.0f,586.0f, -1165.0f,-2892.0f,-4434.0f,-6161.0f,-7405.0f,-7678.0f,-7301.0f,-6104.0f, -4362.0f,-2394.0f,-450.0f,1236.0f,2802.0f,4079.0f,5083.0f,5686.0f, 5878.0f,5951.0f,5838.0f,5276.0f,4393.0f,3437.0f,2329.0f,1188.0f, 570.0f,522.0f,570.0f,602.0f,594.0f,-1.0f,-988.0f,-1976.0f, -3141.0f,-4088.0f,-4691.0f,-4916.0f,-4554.0f,-3976.0f,-3277.0f,-2209.0f, -1462.0f,-1414.0f,-940.0f,240.0f,987.0f,1445.0f,2361.0f,2907.0f, 2610.0f,2513.0f,2770.0f,2562.0f,2545.0f,2867.0f,3084.0f,3397.0f, 3381.0f,2963.0f,2393.0f,1276.0f,-233.0f,-1912.0f,-3775.0f,-5237.0f, -6450.0f,-7526.0f,-7927.0f,-7727.0f,-7116.0f,-5695.0f,-3687.0f,-1462.0f, 843.0f,2979.0f,4762.0f,6103.0f,6971.0f,7260.0f,7027.0f,6577.0f, 5862.0f,4545.0f,2987.0f,1574.0f,120.0f,-1004.0f,-1221.0f,-996.0f, -828.0f,-474.0f,-418.0f,-1125.0f,-1856.0f,-2563.0f,-3422.0f,-3623.0f, -3213.0f,-2811.0f,-2378.0f,-2153.0f,-2426.0f,-2530.0f,-2426.0f,-2225.0f, -1213.0f,594.0f,2208.0f,2794.0f,3051.0f,2794.0f,1742.0f,1349.0f, 1839.0f,2305.0f,2971.0f,3694.0f,3750.0f,3469.0f,2931.0f,1895.0f, 1011.0f,297.0f,-860.0f,-2145.0f,-3831.0f,-5815.0f,-7470.0f,-8642.0f, -9124.0f,-8417.0f,-7124.0f,-5462.0f,-3229.0f,-988.0f,1220.0f,3381.0f, 5292.0f,6810.0f,7702.0f,8103.0f,7766.0f,6746.0f,5734.0f,4304.0f, 2481.0f,1156.0f,337.0f,-129.0f,-17.0f,393.0f,787.0f,385.0f, -852.0f,-1783.0f,-2402.0f,-3261.0f,-3607.0f,-3181.0f,-3872.0f,-5414.0f, -5960.0f,-6369.0f,-6956.0f,-5743.0f,-3486.0f,-1992.0f,-772.0f,634.0f, 2096.0f,2602.0f,3501.0f,5300.0f,5678.0f,5485.0f,5589.0f,5011.0f, 3766.0f,2618.0f,1951.0f,1068.0f,-362.0f,-1623.0f,-2643.0f,-4177.0f, -5863.0f,-6964.0f,-8072.0f,-8939.0f,-8723.0f,-7944.0f,-6899.0f,-5205.0f, -3462.0f,-1567.0f,746.0f,3027.0f,5356.0f,7477.0f,8754.0f,9131.0f, 9091.0f,8529.0f,7340.0f,5886.0f,4192.0f,2288.0f,481.0f,-659.0f, -1213.0f,-1952.0f,-2032.0f,-1936.0f,-2892.0f,-2996.0f,-2571.0f,-2932.0f, -2747.0f,-2474.0f,-3197.0f,-4193.0f,-5084.0f,-5534.0f,-5574.0f,-5245.0f, -4233.0f,-2619.0f,-892.0f,730.0f,2586.0f,4441.0f,6184.0f,7364.0f, 7702.0f,8143.0f,8039.0f,6722.0f,5654.0f,4449.0f,2345.0f,586.0f, -908.0f,-2579.0f,-3912.0f,-5189.0f,-6594.0f,-7494.0f,-8088.0f,-8249.0f, -7927.0f,-7502.0f,-6490.0f,-5141.0f,-3727.0f,-1783.0f,289.0f,2353.0f, 4256.0f,5654.0f,7308.0f,8746.0f,9533.0f,9693.0f,9035.0f,7918.0f, 5951.0f,3549.0f,1831.0f,160.0f,-1679.0f,-2707.0f,-3390.0f,-4321.0f, -4667.0f,-4096.0f,-3599.0f,-3109.0f,-2233.0f,-1759.0f,-1952.0f,-2330.0f, -2554.0f,-3052.0f,-3807.0f,-3864.0f,-3518.0f,-3358.0f,-2691.0f,-1358.0f, 361.0f,2160.0f,3983.0f,5911.0f,7645.0f,8593.0f,8569.0f,8432.0f, 7854.0f,6152.0f,4658.0f,3148.0f,730.0f,-1382.0f,-3454.0f,-5566.0f, -6932.0f,-7960.0f,-8658.0f,-8618.0f,-7984.0f,-7197.0f,-6305.0f,-5004.0f, -3358.0f,-1816.0f,-113.0f,1959.0f,3951.0f,5638.0f,7147.0f,8449.0f, 9203.0f,9380.0f,9147.0f,8376.0f,7099.0f,5734.0f,4192.0f,2513.0f, 939.0f,-587.0f,-2049.0f,-3695.0f,-4739.0f,-4884.0f,-5028.0f,-4699.0f, -3462.0f,-2675.0f,-2699.0f,-2498.0f,-2546.0f,-3358.0f,-3912.0f,-3944.0f, -4000.0f,-3864.0f,-3245.0f,-2595.0f,-1944.0f,-683.0f,1060.0f,3148.0f, 5509.0f,7340.0f,8738.0f,9709.0f,9083.0f,8079.0f,7163.0f,5348.0f, 3549.0f,1847.0f,-362.0f,-2731.0f,-5084.0f,-7213.0f,-8755.0f,-9461.0f, -9413.0f,-8474.0f,-7076.0f,-5695.0f,-3848.0f,-2024.0f,-266.0f,1742.0f, 3766.0f,5493.0f,6826.0f,8023.0f,8609.0f,8577.0f,8328.0f,7830.0f, 6746.0f,5268.0f,3919.0f,2714.0f,1453.0f,104.0f,-1237.0f,-2659.0f, -4241.0f,-5542.0f,-6217.0f,-6297.0f,-5847.0f,-5068.0f,-4241.0f,-3591.0f, -3229.0f,-3301.0f,-3791.0f,-3992.0f,-3679.0f,-3325.0f,-2579.0f,-1559.0f, -868.0f,-370.0f,457.0f,1815.0f,3541.0f,5734.0f,7710.0f,8818.0f, 9533.0f,9059.0f,7621.0f,6553.0f,4875.0f,2899.0f,1204.0f,-1045.0f, -3470.0f,-5815.0f,-7968.0f,-9502.0f,-9791.0f,-9108.0f,-8136.0f,-6514.0f, -4747.0f,-3165.0f,-1205.0f,787.0f,2827.0f,4955.0f,6392.0f,7308.0f, 8216.0f,8288.0f,7702.0f,6955.0f,5734.0f,4120.0f,2513.0f,1293.0f, 232.0f,-707.0f,-1414.0f,-2386.0f,-3534.0f,-4305.0f,-5173.0f,-5912.0f, -5871.0f,-5406.0f,-5004.0f,-4201.0f,-3157.0f,-2731.0f,-2587.0f,-2474.0f, -2571.0f,-2458.0f,-2105.0f,-1518.0f,-659.0f,88.0f,891.0f,1871.0f, 2899.0f,4007.0f,5348.0f,6730.0f,7702.0f,8047.0f,7951.0f,7067.0f, 5533.0f,4176.0f,2401.0f,481.0f,-1478.0f,-3960.0f,-6217.0f,-8184.0f, -9662.0f,-9943.0f,-9285.0f,-8201.0f,-6642.0f,-4835.0f,-3052.0f,-1061.0f, 1116.0f,3204.0f,5091.0f,6898.0f,7959.0f,8127.0f,8119.0f,7348.0f, 6039.0f,4618.0f,2995.0f,1405.0f,48.0f,-1004.0f,-1856.0f,-2418.0f, -3109.0f,-4201.0f,-4972.0f,-5349.0f,-5896.0f,-5743.0f,-4554.0f,-3454.0f, -2900.0f,-2289.0f,-1904.0f,-2314.0f,-2442.0f,-1695.0f,-780.0f,32.0f, 714.0f,1100.0f,835.0f,321.0f,634.0f,1582.0f,2602.0f,4079.0f, 5830.0f,6633.0f,6401.0f,6401.0f,6360.0f,4971.0f,3766.0f,2907.0f, 835.0f,-1053.0f,-3101.0f,-5663.0f,-7622.0f,-9212.0f,-9759.0f,-9052.0f, -8024.0f,-6546.0f,-4803.0f,-3165.0f,-1318.0f,594.0f,2505.0f,4256.0f, 5469.0f,6248.0f,6682.0f,6754.0f,6288.0f,5148.0f,4095.0f,3140.0f, 2120.0f,1148.0f,232.0f,-579.0f,-1253.0f,-2217.0f,-3623.0f,-4611.0f, -5076.0f,-5534.0f,-5639.0f,-5036.0f,-4739.0f,-4924.0f,-4611.0f,-3984.0f, -3574.0f,-2723.0f,-1334.0f,-225.0f,433.0f,1196.0f,1967.0f,2409.0f, 2810.0f,3389.0f,3871.0f,4071.0f,4320.0f,4762.0f,5067.0f,5252.0f, 5348.0f,5075.0f,4569.0f,3646.0f,2288.0f,1076.0f,-627.0f,-2747.0f, -4843.0f,-6883.0f,-8401.0f,-9261.0f,-9164.0f,-8193.0f,-6883.0f,-5317.0f, -3462.0f,-1671.0f,321.0f,2602.0f,4593.0f,6224.0f,7669.0f,8368.0f, 8095.0f,7477.0f,6850.0f,5886.0f,4714.0f,3533.0f,2409.0f,1293.0f, 248.0f,-715.0f,-2040.0f,-3012.0f,-3566.0f,-4442.0f,-4787.0f,-4554.0f, -4892.0f,-5181.0f,-5028.0f,-4755.0f,-4410.0f,-3815.0f,-2755.0f,-1510.0f, -410.0f,754.0f,2047.0f,2963.0f,3485.0f,4184.0f,4762.0f,4826.0f, 4939.0f,4939.0f,4601.0f,4280.0f,4087.0f,4136.0f,3766.0f,3084.0f, 2931.0f,2080.0f,505.0f,-611.0f,-2185.0f,-4080.0f,-5799.0f,-7060.0f, -7719.0f,-8241.0f,-7815.0f,-6683.0f,-5647.0f,-4145.0f,-2289.0f,-780.0f, 1036.0f,3067.0f,4393.0f,5453.0f,6730.0f,7549.0f,7613.0f,7067.0f, 6248.0f,5316.0f,4224.0f,2883.0f,1742.0f,594.0f,-1165.0f,-2346.0f, -2844.0f,-3558.0f,-3775.0f,-3623.0f,-3952.0f,-4273.0f,-4659.0f,-5076.0f, -4988.0f,-4827.0f,-4450.0f,-3446.0f,-2522.0f,-1775.0f,-515.0f,795.0f, 1782.0f,3059.0f,4481.0f,5348.0f,5975.0f,6336.0f,6055.0f,5469.0f, 4810.0f,4192.0f,3590.0f,3084.0f,2698.0f,1734.0f,706.0f,240.0f, -1077.0f,-2691.0f,-3534.0f,-4755.0f,-6217.0f,-7020.0f,-7301.0f,-7518.0f, -7253.0f,-6136.0f,-4731.0f,-3374.0f,-1534.0f,313.0f,2152.0f,4272.0f, 6087.0f,7493.0f,8352.0f,8714.0f,8440.0f,7686.0f,6979.0f,5878.0f, 4312.0f,3067.0f,1349.0f,-844.0f,-2121.0f,-3036.0f,-4185.0f,-4394.0f, -3984.0f,-4337.0f,-4980.0f,-5173.0f,-5398.0f,-6056.0f,-5944.0f,-4996.0f, -4386.0f,-3767.0f,-2715.0f,-1824.0f,-1085.0f,128.0f,1871.0f,3565.0f, 5067.0f,6240.0f,6818.0f,6690.0f,6015.0f,5517.0f,4891.0f,3750.0f, 2891.0f,2240.0f,1140.0f,-153.0f,-1342.0f,-2209.0f,-3213.0f,-4506.0f, -4916.0f,-5044.0f,-5799.0f,-6249.0f,-6112.0f,-6120.0f,-5896.0f,-4707.0f, -3277.0f,-1880.0f,-33.0f,1782.0f,3413.0f,5220.0f,6666.0f,7645.0f, 8264.0f,8416.0f,8360.0f,7951.0f,6866.0f,5662.0f,4007.0f,1726.0f, -482.0f,-2097.0f,-3358.0f,-4530.0f,-4908.0f,-5036.0f,-5703.0f,-6225.0f, -6466.0f,-6787.0f,-6667.0f,-5984.0f,-4964.0f,-3936.0f,-2980.0f,-2097.0f, -1446.0f,-667.0f,586.0f,2176.0f,3967.0f,5573.0f,6706.0f,7131.0f, 6746.0f,6127.0f,5252.0f,4120.0f,3140.0f,2088.0f,819.0f,-386.0f, -1575.0f,-3044.0f,-4466.0f,-4900.0f,-4916.0f,-5382.0f,-5044.0f,-4297.0f, -4522.0f,-4635.0f,-4008.0f,-3390.0f,-2715.0f,-1534.0f,-65.0f,1188.0f, 2353.0f,3501.0f,4601.0f,5646.0f,6328.0f,6882.0f,7308.0f,7396.0f, 7019.0f,6256.0f,5075.0f,3300.0f,1220.0f,-450.0f,-2113.0f,-3591.0f, -4177.0f,-4667.0f,-5550.0f,-6080.0f,-6112.0f,-6530.0f,-6996.0f,-6305.0f, -5165.0f,-4707.0f,-3807.0f,-2249.0f,-1647.0f,-1510.0f,-249.0f,1236.0f, 2112.0f,3694.0f,5654.0f,6384.0f,6481.0f,6714.0f,6280.0f,5067.0f, 4120.0f,3469.0f,1983.0f,216.0f,-1004.0f,-2466.0f,-4209.0f,-5494.0f, -6136.0f,-5920.0f,-5655.0f,-5502.0f,-4466.0f,-3671.0f,-3591.0f,-2868.0f, -1591.0f,-675.0f,152.0f,1461.0f,2610.0f,3365.0f,4240.0f,4979.0f, 5581.0f,6168.0f,6746.0f,7075.0f,6923.0f,6802.0f,5975.0f,4112.0f, 2529.0f,939.0f,-1077.0f,-2603.0f,-3229.0f,-4000.0f,-5462.0f,-6273.0f, -6707.0f,-7598.0f,-7622.0f,-6393.0f,-5494.0f,-4675.0f,-3390.0f,-2595.0f, -2249.0f,-1302.0f,32.0f,1204.0f,2658.0f,3879.0f,4610.0f,5340.0f, 5919.0f,6184.0f,5951.0f,5429.0f,4963.0f,3935.0f,2280.0f,457.0f, -1583.0f,-3727.0f,-5357.0f,-6201.0f,-6787.0f,-7221.0f,-6803.0f,-5823.0f, -5438.0f,-4779.0f,-3285.0f,-2065.0f,-892.0f,851.0f,2353.0f,3124.0f, 3838.0f,4690.0f,5244.0f,5581.0f,5967.0f,6425.0f,6850.0f,7003.0f, 6955.0f,6658.0f,5405.0f,3830.0f,2553.0f,738.0f,-940.0f,-2032.0f, -3277.0f,-4940.0f,-6426.0f,-7349.0f,-8160.0f,-8401.0f,-7598.0f,-6369.0f, -5253.0f,-4201.0f,-2916.0f,-1655.0f,-780.0f,642.0f,2433.0f,3557.0f, 4505.0f,5461.0f,5734.0f,5525.0f,5621.0f,5678.0f,5099.0f,4650.0f, 4200.0f,3092.0f,1726.0f,248.0f,-1494.0f,-3390.0f,-5012.0f,-6040.0f, -6731.0f,-6899.0f,-6570.0f,-6313.0f,-5357.0f,-3872.0f,-2723.0f,-980.0f, 1092.0f,2353.0f,3509.0f,4850.0f,5372.0f,5629.0f,6063.0f,6071.0f, 6144.0f,6208.0f,5919.0f,5718.0f,5348.0f,4120.0f,2971.0f,2023.0f, 650.0f,-458.0f,-1438.0f,-2884.0f,-4410.0f,-6032.0f,-7261.0f,-7903.0f, -8160.0f,-7751.0f,-6835.0f,-5968.0f,-4956.0f,-3478.0f,-2057.0f,-755.0f, 915.0f,2618.0f,3782.0f,4730.0f,5493.0f,5565.0f,5115.0f,4754.0f, 4369.0f,3678.0f,3059.0f,2578.0f,1670.0f,538.0f,-434.0f,-1526.0f, -2699.0f,-3759.0f,-4498.0f,-5221.0f,-5759.0f,-5783.0f,-5534.0f,-4948.0f, -4097.0f,-3068.0f,-1334.0f,546.0f,1831.0f,3445.0f,5067.0f,5758.0f, 6264.0f,6858.0f,6963.0f,6577.0f,6312.0f,5798.0f,4690.0f,3678.0f, 2232.0f,690.0f,-185.0f,-1237.0f,-2161.0f,-2763.0f,-3663.0f,-4691.0f, -5622.0f,-6345.0f,-6626.0f,-6675.0f,-6289.0f,-5494.0f,-4755.0f,-3984.0f, -2964.0f,-1775.0f,-482.0f,1076.0f,2666.0f,3895.0f,4786.0f,5075.0f, 4642.0f,4224.0f,3903.0f,3453.0f,2690.0f,1799.0f,923.0f,-306.0f, -1631.0f,-2554.0f,-3422.0f,-4177.0f,-4514.0f,-4667.0f,-4594.0f,-4402.0f, -4088.0f,-3518.0f,-3093.0f,-2514.0f,-1326.0f,-49.0f,1501.0f,2963.0f, 4288.0f,5846.0f,6497.0f,6858.0f,7485.0f,7172.0f,6320.0f,5862.0f, 4947.0f,3341.0f,1975.0f,425.0f,-1775.0f,-3309.0f,-4426.0f,-5767.0f, -5928.0f,-5478.0f,-5414.0f,-5157.0f,-4715.0f,-4297.0f,-4096.0f,-3486.0f, -2145.0f,-1406.0f,-860.0f,144.0f,409.0f,546.0f,1092.0f,1638.0f, 2264.0f,2923.0f,3477.0f,3702.0f,3421.0f,3051.0f,2610.0f,1766.0f, 899.0f,248.0f,-595.0f,-1743.0f,-2506.0f,-3189.0f,-4209.0f,-4683.0f, -4554.0f,-4378.0f,-3743.0f,-2820.0f,-1888.0f,-932.0f,-209.0f,618.0f, 1646.0f,2457.0f,3517.0f,4746.0f,5694.0f,6384.0f,6658.0f,7083.0f, 7091.0f,6135.0f,5517.0f,4810.0f,3188.0f,1622.0f,377.0f,-1462.0f, -3719.0f,-5406.0f,-6795.0f,-8120.0f,-8514.0f,-8160.0f,-7687.0f,-6723.0f, -5414.0f,-4241.0f,-3149.0f,-1615.0f,72.0f,1413.0f,2778.0f,4096.0f, 4601.0f,4650.0f,4569.0f,4144.0f,3766.0f,3260.0f,2819.0f,2553.0f, 2047.0f,1421.0f,811.0f,32.0f,-474.0f,-940.0f,-1390.0f,-1559.0f, -1775.0f,-2057.0f,-2450.0f,-2811.0f,-3173.0f,-3574.0f,-3647.0f,-3382.0f, -2980.0f,-2426.0f,-1864.0f,-1269.0f,-796.0f,-338.0f,546.0f,1268.0f, 1782.0f,2714.0f,3453.0f,4087.0f,4818.0f,5196.0f,6063.0f,6842.0f, 6609.0f,6617.0f,6232.0f,4650.0f,3084.0f,1726.0f,-113.0f,-1880.0f, -3052.0f,-4731.0f,-6482.0f,-7558.0f,-8827.0f,-9365.0f,-8490.0f,-7365.0f, -5904.0f,-4313.0f,-2916.0f,-1486.0f,-394.0f,995.0f,2794.0f,4096.0f, 5292.0f,6039.0f,5999.0f,5589.0f,4762.0f,3999.0f,3260.0f,2441.0f, 1766.0f,819.0f,-258.0f,-1141.0f,-2289.0f,-3526.0f,-4337.0f,-4811.0f, -5084.0f,-4980.0f,-4265.0f,-3534.0f,-2988.0f,-1976.0f,-739.0f,417.0f, 1895.0f,3485.0f,4858.0f,5605.0f,5927.0f,6103.0f,5541.0f,4650.0f, 4039.0f,3445.0f,2802.0f,2072.0f,1413.0f,1244.0f,530.0f,-924.0f, -1342.0f,-1390.0f,-2265.0f,-2603.0f,-1944.0f,-2121.0f,-3173.0f,-3494.0f, -3743.0f,-4482.0f,-4418.0f,-3888.0f,-3518.0f,-2820.0f,-2193.0f,-1775.0f, -1350.0f,-643.0f,337.0f,1068.0f,1823.0f,2819.0f,3220.0f,3365.0f, 3565.0f,3405.0f,3204.0f,2971.0f,2778.0f,2586.0f,2208.0f,1638.0f, 843.0f,56.0f,-434.0f,-964.0f,-1085.0f,-780.0f,-699.0f,-539.0f, -531.0f,-699.0f,-804.0f,-908.0f,-996.0f,-1069.0f,-1093.0f,-1173.0f, -1446.0f,-1679.0f,-2065.0f,-2434.0f,-2474.0f,-2587.0f,-2442.0f,-1880.0f, -1213.0f,-121.0f,1003.0f,2064.0f,3790.0f,5316.0f,5951.0f,6882.0f, 7878.0f,7348.0f,6409.0f,5935.0f,4465.0f,2232.0f,642.0f,-1101.0f, -3542.0f,-5205.0f,-6594.0f,-7935.0f,-8249.0f,-8152.0f,-7413.0f,-6241.0f, -4996.0f,-3133.0f,-1534.0f,-306.0f,1309.0f,2553.0f,3268.0f,3798.0f, 4184.0f,4216.0f,3581.0f,2947.0f,2449.0f,1790.0f,1076.0f,281.0f, -233.0f,-659.0f,-1438.0f,-1735.0f,-1647.0f,-1695.0f,-1390.0f,-675.0f, 128.0f,754.0f,1542.0f,2144.0f,2433.0f,2835.0f,2770.0f,2441.0f, 2272.0f,1558.0f,642.0f,-17.0f,-1101.0f,-2193.0f,-2771.0f,-3125.0f, -3077.0f,-2996.0f,-2779.0f,-1599.0f,-1221.0f,-1277.0f,208.0f,1244.0f, 1260.0f,1903.0f,2754.0f,2377.0f,1630.0f,1606.0f,1044.0f,-25.0f, -450.0f,-860.0f,-1366.0f,-1679.0f,-1751.0f,-1824.0f,-2024.0f,-1711.0f, -1342.0f,-1310.0f,-860.0f,-330.0f,-113.0f,40.0f,16.0f,240.0f, 168.0f,-81.0f,56.0f,8.0f,-105.0f,-330.0f,-603.0f,-378.0f, -458.0f,-691.0f,-474.0f,-306.0f,-450.0f,-579.0f,-394.0f,-434.0f, -442.0f,-121.0f,56.0f,522.0f,1011.0f,1172.0f,1662.0f,2112.0f, 2176.0f,2481.0f,2987.0f,3180.0f,3043.0f,3228.0f,3300.0f,2337.0f, 1582.0f,1839.0f,1276.0f,-49.0f,-282.0f,-763.0f,-2579.0f,-3928.0f, -4362.0f,-5301.0f,-6313.0f,-6177.0f,-5944.0f,-6217.0f,-5622.0f,-4667.0f, -3984.0f,-2587.0f,-731.0f,505.0f,1718.0f,3437.0f,4264.0f,4288.0f, 4521.0f,4328.0f,3525.0f,2762.0f,1903.0f,1084.0f,32.0f,-892.0f, -1037.0f,-1117.0f,-836.0f,168.0f,1116.0f,2072.0f,3188.0f,3774.0f, 4023.0f,4401.0f,4224.0f,3397.0f,2513.0f,1092.0f,-860.0f,-2884.0f, -4771.0f,-6458.0f,-7743.0f,-8546.0f,-8723.0f,-8361.0f,-7791.0f,-6554.0f, -4787.0f,-2996.0f,-796.0f,1766.0f,4200.0f,6280.0f,8063.0f,9653.0f, 10328.0f,10071.0f,9549.0f,8609.0f,7051.0f,5099.0f,3172.0f,851.0f, -1928.0f,-4265.0f,-6458.0f,-8466.0f,-9333.0f,-9534.0f,-9253.0f,-7992.0f, -6474.0f,-5149.0f,-3566.0f,-1711.0f,-185.0f,1100.0f,2473.0f,3276.0f, 3533.0f,3606.0f,3236.0f,2786.0f,2176.0f,1477.0f,1076.0f,771.0f, 522.0f,224.0f,-129.0f,-185.0f,-201.0f,-266.0f,240.0f,995.0f, 1260.0f,1542.0f,1863.0f,1501.0f,1060.0f,819.0f,473.0f,329.0f, 473.0f,417.0f,361.0f,88.0f,-603.0f,-964.0f,-1277.0f,-1679.0f, -1567.0f,-1414.0f,-1205.0f,-1277.0f,-1663.0f,-1398.0f,-1004.0f,-1093.0f, -627.0f,152.0f,24.0f,-225.0f,0.0f,-266.0f,-964.0f,-1101.0f, -1269.0f,-1719.0f,-1791.0f,-1767.0f,-2008.0f,-1992.0f,-1663.0f,-1294.0f, -956.0f,-129.0f,1164.0f,2377.0f,3630.0f,4899.0f,5750.0f,5935.0f, 6087.0f,6192.0f,5750.0f,5140.0f,4272.0f,2843.0f,939.0f,-1253.0f, -3518.0f,-5550.0f,-6996.0f,-8096.0f,-8530.0f,-8626.0f,-8618.0f,-7847.0f, -6899.0f,-5550.0f,-3623.0f,-1727.0f,337.0f,2602.0f,4561.0f,6160.0f, 7525.0f,8272.0f,8497.0f,8304.0f,7613.0f,6617.0f,5324.0f,3686.0f, 2112.0f,803.0f,-547.0f,-1671.0f,-2040.0f,-2314.0f,-2418.0f,-2057.0f, -1639.0f,-1093.0f,-659.0f,-97.0f,232.0f,-129.0f,-595.0f,-1358.0f, -2434.0f,-3366.0f,-4145.0f,-4924.0f,-5341.0f,-5237.0f,-5020.0f,-4643.0f, -3679.0f,-2362.0f,-1165.0f,329.0f,2031.0f,3164.0f,4095.0f,4818.0f, 5180.0f,5573.0f,5573.0f,5589.0f,5710.0f,5292.0f,4521.0f,3622.0f, 2690.0f,1646.0f,1011.0f,722.0f,289.0f,-185.0f,-916.0f,-1864.0f, -2787.0f,-3534.0f,-4153.0f,-4394.0f,-4233.0f,-4329.0f,-4048.0f,-3574.0f, -3406.0f,-2715.0f,-1679.0f,-804.0f,257.0f,1670.0f,2570.0f,3365.0f, 4240.0f,4642.0f,4907.0f,4915.0f,4850.0f,4915.0f,4328.0f,3373.0f, 2674.0f,1461.0f,-434.0f,-1430.0f,-2201.0f,-3623.0f,-4024.0f,-3848.0f, -3960.0f,-3438.0f,-2731.0f,-2177.0f,-1269.0f,-338.0f,505.0f,1293.0f, 2007.0f,2353.0f,2096.0f,1501.0f,907.0f,136.0f,-635.0f,-1053.0f, -1422.0f,-1824.0f,-2209.0f,-2394.0f,-2386.0f,-2065.0f,-1414.0f,-820.0f, -33.0f,1060.0f,1766.0f,2489.0f,3308.0f,3678.0f,3943.0f,3863.0f, 3606.0f,3349.0f,2658.0f,1951.0f,1365.0f,658.0f,-113.0f,-466.0f, -691.0f,-1029.0f,-892.0f,-675.0f,-747.0f,-515.0f,-474.0f,-595.0f, -370.0f,-482.0f,-892.0f,-1173.0f,-1310.0f,-1478.0f,-2073.0f,-2306.0f, -2193.0f,-2627.0f,-2844.0f,-2498.0f,-2498.0f,-2554.0f,-2201.0f,-1848.0f, -1518.0f,-1045.0f,-555.0f,-193.0f,265.0f,979.0f,1574.0f,1999.0f, 2778.0f,3541.0f,3670.0f,3790.0f,4152.0f,4192.0f,3943.0f,4023.0f, 4176.0f,3847.0f,3092.0f,2433.0f,1630.0f,361.0f,-755.0f,-1840.0f, -2820.0f,-3687.0f,-4643.0f,-5060.0f,-5205.0f,-5671.0f,-5446.0f,-4570.0f, -4121.0f,-3293.0f,-1856.0f,-972.0f,-145.0f,1204.0f,2176.0f,2963.0f, 3871.0f,4353.0f,4626.0f,4336.0f,3477.0f,2891.0f,1983.0f,795.0f, 361.0f,8.0f,-924.0f,-1430.0f,-1061.0f,-1101.0f,-1310.0f,-563.0f, 128.0f,144.0f,176.0f,481.0f,337.0f,-233.0f,-739.0f,-1141.0f, -1872.0f,-2771.0f,-3237.0f,-3807.0f,-4257.0f,-3952.0f,-3960.0f,-3767.0f, -2643.0f,-2024.0f,-1310.0f,-1.0f,779.0f,1413.0f,2321.0f,2754.0f, 3252.0f,3935.0f,3991.0f,4007.0f,4087.0f,3806.0f,3180.0f,2529.0f, 2288.0f,2015.0f,1084.0f,762.0f,1132.0f,530.0f,-161.0f,281.0f, 144.0f,-956.0f,-1261.0f,-1165.0f,-2073.0f,-3093.0f,-3117.0f,-3422.0f, -4522.0f,-4851.0f,-4354.0f,-4602.0f,-4851.0f,-4016.0f,-3390.0f,-3237.0f, -2289.0f,-804.0f,-137.0f,345.0f,1959.0f,3019.0f,2859.0f,3397.0f, 4152.0f,3413.0f,2730.0f,2794.0f,1879.0f,754.0f,425.0f,-57.0f, -812.0f,-1157.0f,-1261.0f,-1599.0f,-1543.0f,-635.0f,-137.0f,313.0f, 1493.0f,1983.0f,1847.0f,2023.0f,2031.0f,1654.0f,979.0f,393.0f, 0.0f,-1101.0f,-2137.0f,-2370.0f,-2763.0f,-2948.0f,-2466.0f,-2153.0f, -1655.0f,-844.0f,-466.0f,168.0f,1180.0f,1542.0f,1999.0f,2545.0f, 2264.0f,1871.0f,1212.0f,56.0f,-763.0f,-1759.0f,-2852.0f,-3149.0f, -3510.0f,-3984.0f,-3574.0f,-3141.0f,-2723.0f,-1703.0f,-691.0f,578.0f, 1879.0f,2698.0f,3565.0f,4168.0f,4457.0f,4425.0f,4248.0f,3911.0f, 2827.0f,1477.0f,449.0f,-916.0f,-2635.0f,-3711.0f,-4506.0f,-5406.0f, -5655.0f,-5422.0f,-5510.0f,-5125.0f,-4032.0f,-3093.0f,-2289.0f,-747.0f, 915.0f,1927.0f,3116.0f,4521.0f,5051.0f,5220.0f,5565.0f,5581.0f, 5228.0f,4553.0f,4047.0f,3630.0f,2947.0f,2393.0f,2152.0f,1477.0f, 730.0f,257.0f,-394.0f,-1101.0f,-1607.0f,-2161.0f,-2779.0f,-3277.0f, -3976.0f,-4715.0f,-4948.0f,-5084.0f,-5325.0f,-5116.0f,-4739.0f,-4442.0f, -3960.0f,-3125.0f,-2161.0f,-1302.0f,-386.0f,514.0f,1148.0f,1694.0f, 2409.0f,3156.0f,3397.0f,3549.0f,4433.0f,4746.0f,4457.0f,4907.0f, 5156.0f,4417.0f,3790.0f,3710.0f,3027.0f,1831.0f,1204.0f,586.0f, -619.0f,-1695.0f,-2571.0f,-3358.0f,-3880.0f,-4097.0f,-4378.0f,-4329.0f, -3944.0f,-3992.0f,-3382.0f,-2081.0f,-1294.0f,-282.0f,1268.0f,2288.0f, 3003.0f,3814.0f,4320.0f,4505.0f,4513.0f,4666.0f,4642.0f,3830.0f, 3244.0f,2891.0f,1349.0f,-266.0f,-828.0f,-1655.0f,-3165.0f,-3647.0f, -3446.0f,-4345.0f,-5253.0f,-4787.0f,-4257.0f,-4297.0f,-3478.0f,-1800.0f, -796.0f,-217.0f,1164.0f,2409.0f,2682.0f,3212.0f,4240.0f,4328.0f, 3879.0f,3879.0f,3590.0f,2272.0f,1124.0f,979.0f,281.0f,-844.0f, -940.0f,-1141.0f,-2185.0f,-2795.0f,-2803.0f,-3245.0f,-3719.0f,-3325.0f, -2787.0f,-2611.0f,-2024.0f,-1165.0f,-482.0f,562.0f,1590.0f,2015.0f, 2626.0f,3501.0f,3686.0f,3790.0f,4344.0f,4417.0f,4047.0f,3951.0f, 3806.0f,3389.0f,2867.0f,2465.0f,2120.0f,1389.0f,546.0f,48.0f, -515.0f,-1149.0f,-1374.0f,-1534.0f,-1896.0f,-2257.0f,-2386.0f,-2514.0f, -2627.0f,-2522.0f,-2619.0f,-2884.0f,-2988.0f,-3269.0f,-3647.0f,-3671.0f, -3679.0f,-3831.0f,-3615.0f,-3253.0f,-3109.0f,-2611.0f,-1791.0f,-932.0f, 120.0f,1317.0f,2698.0f,3975.0f,4634.0f,5662.0f,6874.0f,6987.0f, 6955.0f,7412.0f,6842.0f,5517.0f,4802.0f,3710.0f,1718.0f,96.0f, -1414.0f,-3221.0f,-4699.0f,-5783.0f,-6546.0f,-6763.0f,-6578.0f,-6096.0f, -5317.0f,-4105.0f,-2699.0f,-1350.0f,337.0f,2096.0f,3565.0f,4778.0f, 5822.0f,6481.0f,6441.0f,5862.0f,5413.0f,4658.0f,3461.0f,2449.0f, 1429.0f,-105.0f,-1518.0f,-2514.0f,-3534.0f,-4201.0f,-4378.0f,-4474.0f, -4402.0f,-4008.0f,-3558.0f,-2755.0f,-1912.0f,-1117.0f,-169.0f,345.0f, 634.0f,1180.0f,1196.0f,955.0f,923.0f,425.0f,-306.0f,-836.0f, -1494.0f,-2081.0f,-2346.0f,-2571.0f,-2699.0f,-2635.0f,-2145.0f,-1462.0f, -972.0f,-201.0f,706.0f,1276.0f,1726.0f,2642.0f,3573.0f,3871.0f, 4120.0f,4585.0f,4296.0f,3686.0f,3485.0f,2859.0f,1911.0f,1542.0f, 1068.0f,0.0f,-394.0f,-330.0f,-988.0f,-1318.0f,-603.0f,-571.0f, -747.0f,-33.0f,514.0f,538.0f,522.0f,714.0f,923.0f,779.0f, 690.0f,923.0f,706.0f,168.0f,-161.0f,-579.0f,-1302.0f,-1840.0f, -2169.0f,-2747.0f,-3293.0f,-3671.0f,-4313.0f,-5036.0f,-5237.0f,-5486.0f, -5831.0f,-5598.0f,-5076.0f,-4683.0f,-3912.0f,-2876.0f,-1912.0f,-651.0f, 706.0f,1871.0f,3333.0f,4770.0f,5822.0f,6842.0f,7372.0f,7348.0f, 7581.0f,7292.0f,6433.0f,6071.0f,5124.0f,3469.0f,2104.0f,787.0f, -980.0f,-2418.0f,-3358.0f,-4193.0f,-4884.0f,-5044.0f,-5068.0f,-5036.0f, -4498.0f,-3518.0f,-2571.0f,-1687.0f,-81.0f,1116.0f,1485.0f,2216.0f, 3043.0f,2810.0f,2610.0f,2827.0f,2553.0f,1726.0f,1003.0f,297.0f, -595.0f,-1165.0f,-1615.0f,-2153.0f,-2378.0f,-2322.0f,-2538.0f,-2281.0f, -1462.0f,-812.0f,-539.0f,232.0f,1164.0f,1212.0f,1060.0f,1437.0f, 1309.0f,305.0f,-410.0f,-868.0f,-2105.0f,-3663.0f,-4048.0f,-4546.0f, -5751.0f,-5944.0f,-5470.0f,-5534.0f,-5253.0f,-4080.0f,-2779.0f,-1840.0f, -611.0f,1285.0f,3059.0f,4288.0f,5670.0f,7461.0f,8537.0f,8706.0f, 9059.0f,9276.0f,8352.0f,7420.0f,6802.0f,5244.0f,3413.0f,2208.0f, 489.0f,-1526.0f,-2490.0f,-3165.0f,-4466.0f,-5012.0f,-4442.0f,-4570.0f, -4940.0f,-3992.0f,-3117.0f,-3157.0f,-2386.0f,-924.0f,-354.0f,-161.0f, 754.0f,1381.0f,1148.0f,1236.0f,1558.0f,1188.0f,714.0f,530.0f, 48.0f,-828.0f,-1406.0f,-1808.0f,-2707.0f,-3414.0f,-3510.0f,-3831.0f, -4305.0f,-4072.0f,-3687.0f,-3896.0f,-3647.0f,-2707.0f,-2314.0f,-1864.0f, -547.0f,570.0f,1156.0f,2072.0f,3148.0f,3838.0f,4200.0f,4810.0f, 5605.0f,5589.0f,5260.0f,5581.0f,5517.0f,4409.0f,3943.0f,3943.0f, 3067.0f,1951.0f,1774.0f,1397.0f,56.0f,-426.0f,-410.0f,-1205.0f, -1671.0f,-1302.0f,-1551.0f,-1783.0f,-1583.0f,-1575.0f,-1695.0f,-1486.0f, -1422.0f,-1920.0f,-1735.0f,-1623.0f,-2450.0f,-2691.0f,-2289.0f,-2587.0f, -3036.0f,-2731.0f,-2257.0f,-2281.0f,-2105.0f,-1085.0f,-386.0f,-145.0f, 835.0f,1774.0f,2015.0f,2401.0f,3212.0f,3365.0f,2859.0f,3019.0f, 2939.0f,1815.0f,867.0f,433.0f,-619.0f,-2201.0f,-3229.0f,-3952.0f, -5076.0f,-5879.0f,-6008.0f,-6112.0f,-6032.0f,-5598.0f,-4763.0f,-3663.0f, -2314.0f,-755.0f,1084.0f,2923.0f,4561.0f,6280.0f,7870.0f,8738.0f, 9525.0f,10264.0f,10207.0f,9637.0f,9179.0f,8183.0f,6513.0f,5196.0f, 3734.0f,1622.0f,-129.0f,-1414.0f,-3237.0f,-4715.0f,-5382.0f,-6112.0f, -6875.0f,-6626.0f,-6249.0f,-6434.0f,-5703.0f,-4699.0f,-4321.0f,-3470.0f, -2402.0f,-1719.0f,-1012.0f,-394.0f,72.0f,465.0f,578.0f,730.0f, 722.0f,465.0f,369.0f,120.0f,-161.0f,-354.0f,-434.0f,-715.0f, -796.0f,-474.0f,-707.0f,-804.0f,-410.0f,-418.0f,-611.0f,-233.0f, 40.0f,-193.0f,-89.0f,361.0f,192.0f,104.0f,562.0f,698.0f, 811.0f,1156.0f,1558.0f,2056.0f,2401.0f,2594.0f,3059.0f,3662.0f, 3638.0f,3646.0f,4280.0f,4095.0f,3437.0f,3509.0f,3501.0f,2570.0f, 1839.0f,1678.0f,787.0f,-410.0f,-836.0f,-1510.0f,-2514.0f,-3036.0f, -3366.0f,-4121.0f,-4538.0f,-4570.0f,-4956.0f,-4884.0f,-4586.0f,-4707.0f, -4482.0f,-3944.0f,-3727.0f,-3285.0f,-2458.0f,-1856.0f,-1430.0f,-707.0f, 248.0f,883.0f,1276.0f,2240.0f,2762.0f,2738.0f,3059.0f,3485.0f, 3381.0f,2899.0f,2963.0f,2642.0f,1766.0f,1212.0f,787.0f,-193.0f, -1229.0f,-1703.0f,-2418.0f,-3374.0f,-3607.0f,-3719.0f,-4121.0f,-4048.0f, -3534.0f,-3093.0f,-2338.0f,-1237.0f,-25.0f,1373.0f,2618.0f,3951.0f, 5493.0f,6617.0f,7364.0f,8151.0f,8722.0f,8481.0f,8055.0f,7702.0f, 6625.0f,5316.0f,4240.0f,2722.0f,947.0f,-217.0f,-1735.0f,-3430.0f, -4305.0f,-5092.0f,-6185.0f,-6715.0f,-6522.0f,-6731.0f,-6948.0f,-6249.0f, -5663.0f,-5454.0f,-4659.0f,-3872.0f,-3358.0f,-2860.0f,-2362.0f,-1896.0f, -1647.0f,-1302.0f,-844.0f,-739.0f,-506.0f,-89.0f,257.0f,682.0f, 1132.0f,1686.0f,1823.0f,2168.0f,2778.0f,2963.0f,3212.0f,3654.0f, 3734.0f,3381.0f,3333.0f,3132.0f,2353.0f,1742.0f,1558.0f,851.0f, -249.0f,-699.0f,-988.0f,-1703.0f,-2000.0f,-1767.0f,-1454.0f,-1478.0f, -980.0f,289.0f,811.0f,1252.0f,2449.0f,3172.0f,3324.0f,3806.0f, 4336.0f,4087.0f,3477.0f,3260.0f,2650.0f,1509.0f,779.0f,104.0f, -1237.0f,-2113.0f,-2490.0f,-3478.0f,-4602.0f,-4466.0f,-4185.0f,-5004.0f, -4964.0f,-4040.0f,-4105.0f,-4096.0f,-3261.0f,-2707.0f,-2571.0f,-2354.0f, -1623.0f,-1197.0f,-972.0f,-370.0f,72.0f,80.0f,305.0f,738.0f, 1124.0f,1365.0f,1670.0f,2023.0f,1887.0f,2080.0f,2425.0f,2208.0f, 2120.0f,2313.0f,2080.0f,1509.0f,1220.0f,963.0f,24.0f,-490.0f, -683.0f,-1583.0f,-2089.0f,-2081.0f,-2265.0f,-2370.0f,-1968.0f,-1269.0f, -643.0f,160.0f,1831.0f,3011.0f,3638.0f,5011.0f,6152.0f,6497.0f, 6850.0f,7260.0f,7059.0f,6208.0f,5461.0f,4714.0f,3196.0f,1871.0f, 714.0f,-996.0f,-2426.0f,-3374.0f,-4635.0f,-5904.0f,-6249.0f,-6498.0f, -7285.0f,-7140.0f,-6305.0f,-6273.0f,-5871.0f,-4884.0f,-4209.0f,-3759.0f, -3334.0f,-2554.0f,-2049.0f,-2016.0f,-1454.0f,-916.0f,-892.0f,-474.0f, 152.0f,602.0f,787.0f,1333.0f,2088.0f,2280.0f,2762.0f,3606.0f, 3903.0f,4096.0f,4489.0f,4513.0f,4304.0f,4280.0f,4055.0f,3292.0f, 2698.0f,2023.0f,859.0f,64.0f,-482.0f,-1205.0f,-1647.0f,-1751.0f, -1735.0f,-1735.0f,-1261.0f,-330.0f,-25.0f,642.0f,1726.0f,2039.0f, 2562.0f,3204.0f,3461.0f,3533.0f,3204.0f,2883.0f,2578.0f,1750.0f, 939.0f,257.0f,-515.0f,-1342.0f,-2225.0f,-2892.0f,-3414.0f,-3872.0f, -4177.0f,-4225.0f,-3872.0f,-3815.0f,-3759.0f,-3165.0f,-2739.0f,-2474.0f, -2249.0f,-1695.0f,-1149.0f,-1133.0f,-836.0f,-394.0f,-418.0f,-490.0f, -354.0f,-137.0f,-57.0f,40.0f,409.0f,578.0f,562.0f,907.0f, 1172.0f,1228.0f,1582.0f,1959.0f,1823.0f,1710.0f,1718.0f,1325.0f, 851.0f,546.0f,80.0f,-378.0f,-659.0f,-836.0f,-812.0f,-739.0f, -611.0f,-225.0f,425.0f,1196.0f,1919.0f,2995.0f,4055.0f,4626.0f, 5260.0f,5694.0f,5814.0f,5814.0f,5589.0f,5172.0f,4569.0f,3726.0f, 2537.0f,1309.0f,192.0f,-1012.0f,-2362.0f,-3422.0f,-4072.0f,-5060.0f, -5735.0f,-5807.0f,-6008.0f,-6193.0f,-5799.0f,-5165.0f,-4747.0f,-4129.0f, -3422.0f,-2892.0f,-2530.0f,-2137.0f,-1647.0f,-1438.0f,-1229.0f,-892.0f, -892.0f,-892.0f,-731.0f,-571.0f,-330.0f,-97.0f,377.0f,771.0f, 843.0f,1453.0f,1855.0f,2007.0f,2361.0f,2634.0f,2674.0f,2353.0f, 2425.0f,2329.0f,1734.0f,1381.0f,1228.0f,955.0f,666.0f,674.0f, 923.0f,1076.0f,1212.0f,1574.0f,2056.0f,2369.0f,2626.0f,2947.0f, 3236.0f,3108.0f,2923.0f,2835.0f,2409.0f,1911.0f,1413.0f,771.0f, -17.0f,-876.0f,-1454.0f,-2097.0f,-2988.0f,-3317.0f,-3663.0f,-3976.0f, -3960.0f,-3960.0f,-3799.0f,-3607.0f,-3446.0f,-2916.0f,-2378.0f,-2105.0f, -1719.0f,-1141.0f,-868.0f,-804.0f,-595.0f,-249.0f,-217.0f,-249.0f, 8.0f,32.0f,24.0f,64.0f,176.0f,248.0f,248.0f,393.0f, 530.0f,634.0f,514.0f,409.0f,361.0f,80.0f,-298.0f,-442.0f, -739.0f,-1245.0f,-1390.0f,-1462.0f,-1446.0f,-1277.0f,-1261.0f,-707.0f, -17.0f,265.0f,995.0f,1959.0f,2505.0f,2891.0f,3646.0f,4353.0f, 4553.0f,4698.0f,4947.0f,4794.0f,4610.0f,4272.0f,3590.0f,2987.0f, 2385.0f,1574.0f,722.0f,152.0f,-563.0f,-1286.0f,-1719.0f,-2073.0f, -2490.0f,-2675.0f,-2699.0f,-2803.0f,-2795.0f,-2723.0f,-2667.0f,-2643.0f, -2707.0f,-2546.0f,-2482.0f,-2563.0f,-2458.0f,-2314.0f,-2314.0f,-2490.0f, -2506.0f,-2418.0f,-2466.0f,-2418.0f,-2105.0f,-1960.0f,-1840.0f,-1494.0f, -1157.0f,-884.0f,-603.0f,-274.0f,-169.0f,-41.0f,144.0f,152.0f, 273.0f,361.0f,722.0f,923.0f,891.0f,1309.0f,1903.0f,2144.0f, 2473.0f,3276.0f,3686.0f,3838.0f,4280.0f,4674.0f,4666.0f,4537.0f, 4457.0f,4120.0f,3541.0f,3092.0f,2393.0f,1533.0f,666.0f,-41.0f, -844.0f,-1687.0f,-2169.0f,-2723.0f,-3229.0f,-3430.0f,-3566.0f,-3526.0f, -3165.0f,-3109.0f,-2715.0f,-2113.0f,-1992.0f,-1414.0f,-932.0f,-659.0f, -306.0f,-266.0f,40.0f,80.0f,-9.0f,200.0f,32.0f,-161.0f, -233.0f,-225.0f,-282.0f,-394.0f,-410.0f,-193.0f,-266.0f,-370.0f, -25.0f,-89.0f,-322.0f,-426.0f,-579.0f,-739.0f,-1221.0f,-1294.0f, -1350.0f,-1687.0f,-1671.0f,-1655.0f,-1559.0f,-1294.0f,-1020.0f,-474.0f, -65.0f,232.0f,931.0f,1558.0f,1983.0f,2497.0f,2899.0f,3148.0f, 3180.0f,3228.0f,3196.0f,2634.0f,2337.0f,1999.0f,1421.0f,907.0f, 602.0f,160.0f,-290.0f,-394.0f,-362.0f,-434.0f,-330.0f,104.0f, 369.0f,787.0f,1132.0f,1309.0f,1855.0f,2031.0f,1943.0f,2337.0f, 2288.0f,2039.0f,1774.0f,1333.0f,1132.0f,602.0f,-105.0f,-434.0f, -772.0f,-1438.0f,-1976.0f,-2209.0f,-2322.0f,-2868.0f,-3229.0f,-2852.0f, -3077.0f,-3510.0f,-3358.0f,-3301.0f,-3502.0f,-3687.0f,-3342.0f,-2980.0f, -3036.0f,-2635.0f,-1952.0f,-1518.0f,-1157.0f,-338.0f,578.0f,1003.0f, 1558.0f,2433.0f,2987.0f,3236.0f,3678.0f,3975.0f,4015.0f,3830.0f, 3670.0f,3469.0f,2859.0f,2513.0f,2088.0f,1301.0f,827.0f,417.0f, -225.0f,-627.0f,-780.0f,-988.0f,-1261.0f,-1213.0f,-1037.0f,-1045.0f, -908.0f,-555.0f,-266.0f,-97.0f,160.0f,425.0f,497.0f,473.0f, 722.0f,674.0f,441.0f,546.0f,522.0f,305.0f,80.0f,8.0f, -17.0f,-249.0f,-418.0f,-274.0f,-346.0f,-627.0f,-563.0f,-675.0f, -988.0f,-1012.0f,-1157.0f,-1294.0f,-1277.0f,-1253.0f,-1181.0f,-1197.0f, -940.0f,-402.0f,-298.0f,-57.0f,690.0f,1060.0f,1260.0f,1590.0f, 1943.0f,2144.0f,1967.0f,1919.0f,1983.0f,1493.0f,1044.0f,706.0f, 8.0f,-675.0f,-1245.0f,-1984.0f,-2619.0f,-2916.0f,-3269.0f,-3623.0f, -3502.0f,-3325.0f,-3261.0f,-2731.0f,-2297.0f,-2032.0f,-1366.0f,-988.0f, -635.0f,-1.0f,385.0f,915.0f,1309.0f,1525.0f,2120.0f,2345.0f, 2473.0f,2907.0f,3019.0f,3140.0f,3180.0f,3172.0f,3405.0f,3236.0f, 3124.0f,3381.0f,3076.0f,2794.0f,2754.0f,2272.0f,1734.0f,1309.0f, 779.0f,232.0f,-370.0f,-804.0f,-1085.0f,-1727.0f,-2016.0f,-1832.0f, -2249.0f,-2490.0f,-1896.0f,-1824.0f,-1968.0f,-1526.0f,-1012.0f,-892.0f, -908.0f,-547.0f,-169.0f,-450.0f,-434.0f,-137.0f,-426.0f,-603.0f, -635.0f,-908.0f,-1189.0f,-1342.0f,-1510.0f,-1791.0f,-1976.0f,-1928.0f, -2105.0f,-2161.0f,-1960.0f,-2024.0f,-1824.0f,-1534.0f,-1462.0f,-1020.0f, -675.0f,-458.0f,-65.0f,144.0f,618.0f,1019.0f,1156.0f,1702.0f, 2080.0f,2128.0f,2337.0f,2369.0f,2393.0f,2288.0f,1879.0f,1839.0f, 1622.0f,947.0f,642.0f,417.0f,-266.0f,-852.0f,-1109.0f,-1422.0f, -1880.0f,-2121.0f,-1968.0f,-2024.0f,-2089.0f,-1551.0f,-1117.0f,-868.0f, -121.0f,650.0f,1148.0f,1766.0f,2481.0f,3067.0f,3469.0f,3718.0f, 4047.0f,4128.0f,3927.0f,3838.0f,3405.0f,2810.0f,2425.0f,1774.0f, 939.0f,305.0f,-386.0f,-1189.0f,-1976.0f,-2563.0f,-3173.0f,-3751.0f, -4088.0f,-4386.0f,-4602.0f,-4643.0f,-4594.0f,-4554.0f,-4265.0f,-3936.0f, -3655.0f,-3358.0f,-2892.0f,-2322.0f,-1912.0f,-1470.0f,-812.0f,-241.0f, 208.0f,714.0f,1124.0f,1373.0f,1566.0f,1646.0f,1566.0f,1542.0f, 1381.0f,1060.0f,771.0f,578.0f,377.0f,56.0f,-113.0f,88.0f, 88.0f,-73.0f,232.0f,746.0f,1052.0f,1333.0f,2064.0f,2843.0f, 3140.0f,3549.0f,4232.0f,4618.0f,4778.0f,4842.0f,4850.0f,4706.0f, 4344.0f,3863.0f,3268.0f,2570.0f,1879.0f,1084.0f,48.0f,-659.0f, -1382.0f,-2418.0f,-3157.0f,-3711.0f,-4337.0f,-4787.0f,-5181.0f,-5277.0f, -5213.0f,-5277.0f,-5092.0f,-4586.0f,-4129.0f,-3623.0f,-3101.0f,-2354.0f, -1446.0f,-956.0f,-282.0f,546.0f,1060.0f,1493.0f,1831.0f,2248.0f, 2537.0f,2385.0f,2385.0f,2345.0f,1943.0f,1614.0f,1252.0f,706.0f, 168.0f,-450.0f,-988.0f,-1518.0f,-2057.0f,-2314.0f,-2667.0f,-2980.0f, -2779.0f,-2546.0f,-2386.0f,-1896.0f,-1045.0f,-298.0f,232.0f,1156.0f, 2064.0f,2481.0f,2947.0f,3381.0f,3533.0f,3573.0f,3533.0f,3260.0f, 2859.0f,2465.0f,2064.0f,1453.0f,875.0f,505.0f,0.0f,-603.0f, -980.0f,-1061.0f,-1350.0f,-1567.0f,-1430.0f,-1302.0f,-1269.0f,-1141.0f, -796.0f,-482.0f,-121.0f,216.0f,425.0f,875.0f,1276.0f,1317.0f, 1542.0f,1879.0f,1847.0f,1879.0f,1879.0f,1774.0f,1670.0f,1244.0f, 979.0f,771.0f,192.0f,-298.0f,-643.0f,-1165.0f,-1791.0f,-2257.0f, -2715.0f,-3221.0f,-3542.0f,-3711.0f,-4000.0f,-4113.0f,-3815.0f,-3631.0f, -3599.0f,-3004.0f,-2169.0f,-1655.0f,-996.0f,-1.0f,923.0f,1421.0f, 1782.0f,2393.0f,2754.0f,2658.0f,2802.0f,2891.0f,2666.0f,2433.0f, 2200.0f,1799.0f,1429.0f,1068.0f,650.0f,385.0f,208.0f,0.0f, -105.0f,-89.0f,-81.0f,-1.0f,120.0f,257.0f,481.0f,658.0f, 811.0f,1052.0f,1276.0f,1525.0f,1726.0f,1823.0f,1975.0f,2048.0f, 1991.0f,2056.0f,1975.0f,1750.0f,1542.0f,1252.0f,939.0f,473.0f, -57.0f,-466.0f,-988.0f,-1663.0f,-2177.0f,-2683.0f,-3245.0f,-3719.0f, -4000.0f,-4169.0f,-4402.0f,-4394.0f,-4000.0f,-3679.0f,-3350.0f,-2490.0f, -1607.0f,-980.0f,-362.0f,489.0f,1188.0f,1413.0f,1879.0f,2369.0f, 2393.0f,2489.0f,2682.0f,2481.0f,2385.0f,2321.0f,2064.0f,1815.0f, 1558.0f,1349.0f,1052.0f,779.0f,690.0f,457.0f,281.0f,168.0f, -89.0f,-209.0f,-338.0f,-579.0f,-651.0f,-763.0f,-924.0f,-996.0f, -1037.0f,-956.0f,-948.0f,-860.0f,-627.0f,-547.0f,-386.0f,-137.0f, -73.0f,72.0f,208.0f,240.0f,345.0f,192.0f,112.0f,160.0f, -145.0f,-362.0f,-402.0f,-667.0f,-924.0f,-1109.0f,-1245.0f,-1310.0f, -1462.0f,-1462.0f,-1310.0f,-1237.0f,-1061.0f,-884.0f,-498.0f,-9.0f, 248.0f,674.0f,1244.0f,1630.0f,1951.0f,2184.0f,2449.0f,2722.0f, 2754.0f,2722.0f,2762.0f,2706.0f,2513.0f,2288.0f,2112.0f,1903.0f, 1550.0f,1228.0f,987.0f,634.0f,200.0f,-25.0f,-394.0f,-788.0f, -1029.0f,-1470.0f,-1864.0f,-2049.0f,-2297.0f,-2611.0f,-2868.0f,-2900.0f, -2924.0f,-3052.0f,-2884.0f,-2603.0f,-2394.0f,-2081.0f,-1695.0f,-1245.0f, -820.0f,-531.0f,-201.0f,120.0f,345.0f,449.0f,554.0f,722.0f, 746.0f,634.0f,626.0f,473.0f,192.0f,88.0f,-129.0f,-298.0f, -241.0f,-394.0f,-555.0f,-322.0f,-193.0f,-201.0f,224.0f,722.0f, 915.0f,1252.0f,1750.0f,2088.0f,2264.0f,2465.0f,2746.0f,2827.0f, 2778.0f,2802.0f,2666.0f,2473.0f,2296.0f,1975.0f,1662.0f,1381.0f, 1011.0f,642.0f,257.0f,-177.0f,-723.0f,-1125.0f,-1454.0f,-1767.0f, -2000.0f,-2257.0f,-2563.0f,-2707.0f,-2795.0f,-2988.0f,-3085.0f,-3004.0f, -2892.0f,-2828.0f,-2611.0f,-2249.0f,-1904.0f,-1494.0f,-1085.0f,-699.0f, -249.0f,88.0f,313.0f,578.0f,738.0f,819.0f,835.0f,787.0f, 779.0f,674.0f,457.0f,313.0f,152.0f,-73.0f,-306.0f,-434.0f, -539.0f,-635.0f,-675.0f,-627.0f,-466.0f,-306.0f,-145.0f,208.0f, 554.0f,803.0f,1084.0f,1429.0f,1718.0f,1847.0f,1887.0f,2047.0f, 2072.0f,1943.0f,1863.0f,1710.0f,1558.0f,1429.0f,1156.0f,915.0f, 754.0f,514.0f,200.0f,-65.0f,-282.0f,-547.0f,-828.0f,-1020.0f, -1157.0f,-1334.0f,-1494.0f,-1599.0f,-1639.0f,-1687.0f,-1759.0f,-1759.0f, -1663.0f,-1575.0f,-1510.0f,-1422.0f,-1245.0f,-964.0f,-739.0f,-547.0f, -274.0f,8.0f,192.0f,337.0f,546.0f,714.0f,771.0f,851.0f, 995.0f,1028.0f,939.0f,1003.0f,995.0f,819.0f,706.0f,626.0f, 546.0f,433.0f,377.0f,337.0f,232.0f,224.0f,265.0f,273.0f, 305.0f,449.0f,602.0f,610.0f,682.0f,819.0f,891.0f,811.0f, 746.0f,787.0f,714.0f,674.0f,586.0f,505.0f,554.0f,473.0f, 329.0f,289.0f,240.0f,144.0f,-25.0f,-137.0f,-217.0f,-386.0f, -547.0f,-667.0f,-772.0f,-796.0f,-924.0f,-1037.0f,-1004.0f,-1045.0f, -1077.0f,-1101.0f,-1029.0f,-940.0f,-860.0f,-747.0f,-627.0f,-482.0f, -346.0f,-249.0f,-161.0f,-41.0f,96.0f,136.0f,152.0f,273.0f, 353.0f,353.0f,361.0f,337.0f,385.0f,433.0f,345.0f,425.0f, 449.0f,337.0f,297.0f,281.0f,281.0f,289.0f,216.0f,240.0f, 248.0f,232.0f,240.0f,168.0f,216.0f,313.0f,313.0f,321.0f, 393.0f,465.0f,441.0f,377.0f,449.0f,538.0f,586.0f,538.0f, 505.0f,610.0f,602.0f,530.0f,489.0f,457.0f,465.0f,385.0f, 265.0f,257.0f,176.0f,40.0f,-81.0f,-113.0f,-153.0f,-258.0f, -298.0f,-338.0f,-418.0f,-466.0f,-539.0f,-587.0f,-563.0f,-555.0f, -611.0f,-587.0f,-531.0f,-506.0f,-474.0f,-474.0f,-490.0f,-458.0f, -458.0f,-498.0f,-482.0f,-450.0f,-426.0f,-434.0f,-482.0f,-434.0f, -402.0f,-378.0f,-306.0f,-233.0f,-193.0f,-217.0f,-258.0f,-258.0f, -282.0f,-298.0f,-241.0f,-177.0f,-201.0f,-193.0f,-121.0f,-73.0f, 0.0f,72.0f,200.0f,345.0f,449.0f,546.0f,674.0f,835.0f, 899.0f,939.0f,1028.0f,1076.0f,1084.0f,1019.0f,971.0f,979.0f, 947.0f,875.0f,795.0f,746.0f,738.0f,634.0f,546.0f,530.0f, 473.0f,441.0f,329.0f,265.0f,248.0f,200.0f,152.0f,56.0f, 40.0f,8.0f,-73.0f,-121.0f,-177.0f,-233.0f,-298.0f,-362.0f, -450.0f,-555.0f,-619.0f,-659.0f,-755.0f,-812.0f,-820.0f,-900.0f, -988.0f,-988.0f,-988.0f,-1020.0f,-1012.0f,-948.0f,-892.0f,-860.0f, -812.0f,-739.0f,-707.0f,-635.0f,-555.0f,-498.0f,-386.0f,-314.0f, -258.0f,-201.0f,-153.0f,-97.0f,-25.0f,104.0f,184.0f,200.0f, 265.0f,321.0f,337.0f,377.0f,409.0f,441.0f,481.0f,538.0f, 570.0f,570.0f,562.0f,538.0f,522.0f,530.0f,505.0f,489.0f, 530.0f,562.0f,618.0f,642.0f,634.0f,706.0f,722.0f,682.0f, 698.0f,714.0f,690.0f,634.0f,586.0f,489.0f,393.0f,313.0f, 224.0f,104.0f,-9.0f,-113.0f,-201.0f,-249.0f,-330.0f,-386.0f, -426.0f,-482.0f,-506.0f,-531.0f,-563.0f,-555.0f,-539.0f,-531.0f, -498.0f,-434.0f,-378.0f,-346.0f,-338.0f,-290.0f,-282.0f,-290.0f, -249.0f,-201.0f,-185.0f,-153.0f,-73.0f,-33.0f,-65.0f,-81.0f, -89.0f,-129.0f,-137.0f,-137.0f,-137.0f,-193.0f,-225.0f,-225.0f, -266.0f,-306.0f,-322.0f,-322.0f,-370.0f,-386.0f,-394.0f,-434.0f, -434.0f,-450.0f,-474.0f,-490.0f,-458.0f,-418.0f,-410.0f,-418.0f, -386.0f,-354.0f,-370.0f,-338.0f,-330.0f,-306.0f,-241.0f,-225.0f, -169.0f,-145.0f,-89.0f,8.0f,96.0f,216.0f,297.0f,425.0f, 514.0f,586.0f,674.0f,714.0f,754.0f,803.0f,803.0f,787.0f, 787.0f,771.0f,714.0f,642.0f,554.0f,481.0f,433.0f,369.0f, 289.0f,248.0f,184.0f,72.0f,16.0f,-1.0f,-33.0f,-73.0f, -97.0f,-81.0f,-89.0f,-89.0f,-105.0f,-129.0f,-137.0f,-145.0f, -145.0f,-153.0f,-129.0f,-137.0f,-145.0f,-169.0f,-209.0f,-225.0f, -290.0f,-354.0f,-370.0f,-402.0f,-442.0f,-450.0f,-442.0f,-498.0f, -498.0f,-466.0f,-474.0f,-442.0f,-394.0f,-362.0f,-338.0f,-274.0f, -209.0f,-177.0f,-81.0f,-9.0f,16.0f,80.0f,152.0f,216.0f, 232.0f,248.0f,289.0f,297.0f,289.0f,273.0f,257.0f,216.0f, 184.0f,160.0f,128.0f,120.0f,112.0f,96.0f,64.0f,24.0f, 32.0f,-1.0f,-25.0f,0.0f,-1.0f,-9.0f,-1.0f,-9.0f, 0 }; t_CKUINT dope_size = 10240; // data for eee.raw... SAMPLE eee_data[] = { -458.0f,746.0f,297.0f,1807.0f,4160.0f,3879.0f,3646.0f,5204.0f, 4802.0f,4385.0f,5951.0f,5662.0f,4497.0f,4425.0f,4031.0f,3493.0f, 3389.0f,2497.0f,1317.0f,971.0f,-137.0f,-1334.0f,-1486.0f,-2137.0f, -2820.0f,-2996.0f,-3647.0f,-4474.0f,-4570.0f,-4402.0f,-4795.0f,-5542.0f, -5871.0f,-5044.0f,-5181.0f,-6618.0f,-5341.0f,-2948.0f,-4410.0f,-5622.0f, -2057.0f,-627.0f,-3068.0f,-1093.0f,2883.0f,987.0f,-322.0f,4417.0f, 5895.0f,2730.0f,4216.0f,7501.0f,5589.0f,4449.0f,7388.0f,7453.0f, 5204.0f,5581.0f,6232.0f,4995.0f,4248.0f,3766.0f,2730.0f,2248.0f, 875.0f,-772.0f,-788.0f,-2000.0f,-5422.0f,-6546.0f,-5373.0f,-6795.0f, -9036.0f,-7911.0f,-7775.0f,-10987.0f,-10891.0f,-7630.0f,-8538.0f,-11052.0f, -8996.0f,-7301.0f,-8538.0f,-7197.0f,-4940.0f,-5261.0f,-5181.0f,-3117.0f, -1237.0f,-635.0f,-394.0f,-458.0f, 0 }; t_CKUINT eee_size = 92; // data for fwavblnk.raw... SAMPLE fwavblnk_data[] = { 0.0f,1606.0f,3212.0f,4802.0f,6392.0f,7967.0f,9509.0f,11035.0f, 12536.0f,14014.0f,15444.0f,16841.0f,18207.0f,19516.0f,20785.0f,22005.0f, 23170.0f,24278.0f,25330.0f,26318.0f,27242.0f,28109.0f,28896.0f,29619.0f, 30278.0f,30848.0f,31354.0f,31788.0f,32141.0f,32414.0f,32615.0f,32727.0f, 32767.0f,32727.0f,32615.0f,32414.0f,32141.0f,31788.0f,31354.0f,30848.0f, 30278.0f,29619.0f,28896.0f,28109.0f,27242.0f,26318.0f,25330.0f,24278.0f, 23170.0f,22005.0f,20785.0f,19516.0f,18207.0f,16841.0f,15444.0f,14014.0f, 12536.0f,11035.0f,9509.0f,7967.0f,6392.0f,4802.0f,3212.0f,1606.0f, 0.0f,1606.0f,3212.0f,4802.0f,6392.0f,7967.0f,9509.0f,11035.0f, 12536.0f,14014.0f,15444.0f,16841.0f,18207.0f,19516.0f,20785.0f,22005.0f, 23170.0f,24278.0f,25330.0f,26318.0f,27242.0f,28109.0f,28896.0f,29619.0f, 30278.0f,30848.0f,31354.0f,31788.0f,32141.0f,32414.0f,32615.0f,32727.0f, 32767.0f,32727.0f,32615.0f,32414.0f,32141.0f,31788.0f,31354.0f,30848.0f, 30278.0f,29619.0f,28896.0f,28109.0f,27242.0f,26318.0f,25330.0f,24278.0f, 23170.0f,22005.0f,20785.0f,19516.0f,18207.0f,16841.0f,15444.0f,14014.0f, 12536.0f,11035.0f,9509.0f,7967.0f,6392.0f,4802.0f,3212.0f,1606.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT fwavblnk_size = 256; // data for halfwave.raw... SAMPLE halfwave_data[] = { 0.0f,803.0f,1606.0f,2409.0f,3212.0f,4015.0f,4802.0f,5605.0f, 6392.0f,7180.0f,7967.0f,8738.0f,9509.0f,10272.0f,11035.0f,11798.0f, 12536.0f,13275.0f,14014.0f,14729.0f,15444.0f,16151.0f,16841.0f,17532.0f, 18207.0f,18865.0f,19516.0f,20158.0f,20785.0f,21403.0f,22005.0f,22592.0f, 23170.0f,23732.0f,24278.0f,24808.0f,25330.0f,25828.0f,26318.0f,26784.0f, 27242.0f,27684.0f,28109.0f,28511.0f,28896.0f,29266.0f,29619.0f,29957.0f, 30278.0f,30575.0f,30848.0f,31113.0f,31354.0f,31579.0f,31788.0f,31972.0f, 32141.0f,32286.0f,32414.0f,32527.0f,32615.0f,32679.0f,32727.0f,32759.0f, 32767.0f,32759.0f,32727.0f,32679.0f,32615.0f,32527.0f,32414.0f,32286.0f, 32141.0f,31972.0f,31788.0f,31579.0f,31354.0f,31113.0f,30848.0f,30575.0f, 30278.0f,29957.0f,29619.0f,29266.0f,28896.0f,28511.0f,28109.0f,27684.0f, 27242.0f,26784.0f,26318.0f,25828.0f,25330.0f,24808.0f,24278.0f,23732.0f, 23170.0f,22592.0f,22005.0f,21403.0f,20785.0f,20158.0f,19516.0f,18865.0f, 18207.0f,17532.0f,16841.0f,16151.0f,15444.0f,14729.0f,14014.0f,13275.0f, 12536.0f,11798.0f,11035.0f,10272.0f,9509.0f,8738.0f,7967.0f,7180.0f, 6392.0f,5605.0f,4802.0f,4015.0f,3212.0f,2409.0f,1606.0f,803.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT halfwave_size = 256; // data for impuls10.raw... SAMPLE impuls10_data[] = { 32767.0f,32390.0f,31266.0f,29443.0f,27001.0f,24021.0f,20624.0f,16938.0f, 13099.0f,9252.0f,5525.0f,2039.0f,-1093.0f,-3775.0f,-5952.0f,-7566.0f, -8618.0f,-9116.0f,-9092.0f,-8610.0f,-7735.0f,-6554.0f,-5173.0f,-3687.0f, -2185.0f,-772.0f,473.0f,1509.0f,2264.0f,2722.0f,2875.0f,2730.0f, 2313.0f,1670.0f,851.0f,-81.0f,-1077.0f,-2049.0f,-2948.0f,-3727.0f, -4321.0f,-4723.0f,-4916.0f,-4876.0f,-4635.0f,-4209.0f,-3639.0f,-2956.0f, -2209.0f,-1462.0f,-747.0f,-113.0f,393.0f,762.0f,955.0f,979.0f, 835.0f,530.0f,88.0f,-442.0f,-1045.0f,-1671.0f,-2265.0f,-2820.0f, -3277.0f,-3615.0f,-3823.0f,-3880.0f,-3783.0f,-3558.0f,-3205.0f,-2763.0f, -2249.0f,-1719.0f,-1181.0f,-691.0f,-266.0f,56.0f,265.0f,345.0f, 289.0f,112.0f,-169.0f,-547.0f,-996.0f,-1478.0f,-1960.0f,-2418.0f, -2811.0f,-3133.0f,-3350.0f,-3454.0f,-3430.0f,-3293.0f,-3052.0f,-2715.0f, -2314.0f,-1880.0f,-1422.0f,-988.0f,-603.0f,-282.0f,-57.0f,56.0f, 64.0f,-33.0f,-241.0f,-547.0f,-916.0f,-1334.0f,-1767.0f,-2177.0f, -2563.0f,-2884.0f,-3125.0f,-3261.0f,-3293.0f,-3213.0f,-3036.0f,-2755.0f, -2410.0f,-2024.0f,-1599.0f,-1181.0f,-796.0f,-458.0f,-209.0f,-49.0f, 0.0f,-49.0f,-209.0f,-458.0f,-796.0f,-1181.0f,-1599.0f,-2024.0f, -2410.0f,-2755.0f,-3036.0f,-3213.0f,-3293.0f,-3261.0f,-3125.0f,-2884.0f, -2563.0f,-2177.0f,-1767.0f,-1334.0f,-916.0f,-547.0f,-241.0f,-33.0f, 64.0f,56.0f,-57.0f,-282.0f,-603.0f,-988.0f,-1422.0f,-1880.0f, -2314.0f,-2715.0f,-3052.0f,-3293.0f,-3430.0f,-3454.0f,-3350.0f,-3133.0f, -2811.0f,-2418.0f,-1960.0f,-1478.0f,-996.0f,-547.0f,-169.0f,112.0f, 289.0f,345.0f,265.0f,56.0f,-266.0f,-691.0f,-1181.0f,-1719.0f, -2249.0f,-2763.0f,-3205.0f,-3558.0f,-3783.0f,-3880.0f,-3823.0f,-3615.0f, -3277.0f,-2820.0f,-2265.0f,-1671.0f,-1045.0f,-442.0f,88.0f,530.0f, 835.0f,979.0f,955.0f,762.0f,393.0f,-113.0f,-747.0f,-1462.0f, -2209.0f,-2956.0f,-3639.0f,-4209.0f,-4635.0f,-4876.0f,-4916.0f,-4723.0f, -4321.0f,-3727.0f,-2948.0f,-2049.0f,-1077.0f,-81.0f,851.0f,1670.0f, 2313.0f,2730.0f,2875.0f,2722.0f,2264.0f,1509.0f,473.0f,-772.0f, -2185.0f,-3687.0f,-5173.0f,-6554.0f,-7735.0f,-8610.0f,-9092.0f,-9116.0f, -8618.0f,-7566.0f,-5952.0f,-3775.0f,-1093.0f,2039.0f,5525.0f,9252.0f, 13099.0f,16938.0f,20624.0f,24021.0f,27001.0f,29443.0f,31266.0f,32390.0f, 0 }; t_CKUINT impuls10_size = 256; // data for impuls20.raw... SAMPLE impuls20_data[] = { 32767.0f,31370.0f,27378.0f,21395.0f,14279.0f,7003.0f,538.0f,-4362.0f, -7277.0f,-8128.0f,-7173.0f,-4964.0f,-2169.0f,489.0f,2481.0f,3445.0f, 3300.0f,2200.0f,522.0f,-1294.0f,-2828.0f,-3743.0f,-3888.0f,-3285.0f, -2145.0f,-788.0f,465.0f,1325.0f,1614.0f,1293.0f,489.0f,-571.0f, -1639.0f,-2442.0f,-2811.0f,-2675.0f,-2105.0f,-1253.0f,-330.0f,417.0f, 843.0f,843.0f,433.0f,-249.0f,-1053.0f,-1767.0f,-2217.0f,-2314.0f, -2048.0f,-1486.0f,-780.0f,-113.0f,361.0f,530.0f,369.0f,-73.0f, -691.0f,-1318.0f,-1808.0f,-2040.0f,-1968.0f,-1615.0f,-1077.0f,-490.0f, 0.0f,281.0f,281.0f,16.0f,-442.0f,-988.0f,-1486.0f,-1808.0f, -1880.0f,-1687.0f,-1286.0f,-780.0f,-290.0f,48.0f,176.0f,56.0f, -266.0f,-731.0f,-1213.0f,-1583.0f,-1767.0f,-1711.0f,-1438.0f,-1012.0f, -547.0f,-153.0f,64.0f,64.0f,-145.0f,-523.0f,-972.0f,-1374.0f, -1639.0f,-1695.0f,-1543.0f,-1205.0f,-772.0f,-362.0f,-65.0f,40.0f, -57.0f,-354.0f,-755.0f,-1173.0f,-1502.0f,-1655.0f,-1607.0f,-1358.0f, -980.0f,-563.0f,-217.0f,-9.0f,-9.0f,-209.0f,-555.0f,-972.0f, -1342.0f,-1583.0f,-1639.0f,-1486.0f,-1173.0f,-763.0f,-378.0f,-97.0f, 0.0f,-97.0f,-378.0f,-763.0f,-1173.0f,-1486.0f,-1639.0f,-1583.0f, -1342.0f,-972.0f,-555.0f,-209.0f,-9.0f,-9.0f,-217.0f,-563.0f, -980.0f,-1358.0f,-1607.0f,-1655.0f,-1502.0f,-1173.0f,-755.0f,-354.0f, -57.0f,40.0f,-65.0f,-362.0f,-772.0f,-1205.0f,-1543.0f,-1695.0f, -1639.0f,-1374.0f,-972.0f,-523.0f,-145.0f,64.0f,64.0f,-153.0f, -547.0f,-1012.0f,-1438.0f,-1711.0f,-1767.0f,-1583.0f,-1213.0f,-731.0f, -266.0f,56.0f,176.0f,48.0f,-290.0f,-780.0f,-1286.0f,-1687.0f, -1880.0f,-1808.0f,-1486.0f,-988.0f,-442.0f,16.0f,281.0f,281.0f, 0.0f,-490.0f,-1077.0f,-1615.0f,-1968.0f,-2040.0f,-1808.0f,-1318.0f, -691.0f,-73.0f,369.0f,530.0f,361.0f,-113.0f,-780.0f,-1486.0f, -2048.0f,-2314.0f,-2217.0f,-1767.0f,-1053.0f,-249.0f,433.0f,843.0f, 843.0f,417.0f,-330.0f,-1253.0f,-2105.0f,-2675.0f,-2811.0f,-2442.0f, -1639.0f,-571.0f,489.0f,1293.0f,1614.0f,1325.0f,465.0f,-788.0f, -2145.0f,-3285.0f,-3888.0f,-3743.0f,-2828.0f,-1294.0f,522.0f,2200.0f, 3300.0f,3445.0f,2481.0f,489.0f,-2169.0f,-4964.0f,-7173.0f,-8128.0f, -7277.0f,-4362.0f,538.0f,7003.0f,14279.0f,21395.0f,27378.0f,31370.0f, 0 }; t_CKUINT impuls20_size = 256; // data for impuls40.raw... SAMPLE impuls40_data[] = { 32767.0f,27563.0f,14850.0f,1357.0f,-6594.0f,-6867.0f,-2153.0f,2570.0f, 3750.0f,1301.0f,-2057.0f,-3446.0f,-2065.0f,489.0f,1927.0f,1196.0f, -820.0f,-2241.0f,-1944.0f,-338.0f,1036.0f,1036.0f,-217.0f,-1534.0f, -1759.0f,-788.0f,441.0f,835.0f,104.0f,-1029.0f,-1551.0f,-1037.0f, 0.0f,610.0f,281.0f,-635.0f,-1310.0f,-1149.0f,-338.0f,369.0f, 353.0f,-330.0f,-1061.0f,-1181.0f,-603.0f,120.0f,345.0f,-113.0f, -820.0f,-1133.0f,-788.0f,-113.0f,265.0f,32.0f,-587.0f,-1037.0f, -908.0f,-338.0f,144.0f,120.0f,-378.0f,-900.0f,-964.0f,-531.0f, 0.0f,144.0f,-201.0f,-739.0f,-964.0f,-683.0f,-161.0f,120.0f, -73.0f,-563.0f,-908.0f,-796.0f,-330.0f,48.0f,8.0f,-402.0f, -820.0f,-860.0f,-490.0f,-57.0f,48.0f,-249.0f,-699.0f,-876.0f, -627.0f,-185.0f,40.0f,-129.0f,-563.0f,-844.0f,-731.0f,-322.0f, 0.0f,-41.0f,-418.0f,-780.0f,-804.0f,-466.0f,-81.0f,0.0f, -282.0f,-683.0f,-828.0f,-595.0f,-185.0f,8.0f,-161.0f,-563.0f, -820.0f,-699.0f,-314.0f,-17.0f,-73.0f,-434.0f,-763.0f,-772.0f, -450.0f,-81.0f,-17.0f,-306.0f,-683.0f,-812.0f,-571.0f,-185.0f, 0.0f,-185.0f,-571.0f,-812.0f,-683.0f,-306.0f,-17.0f,-81.0f, -450.0f,-772.0f,-763.0f,-434.0f,-73.0f,-17.0f,-314.0f,-699.0f, -820.0f,-563.0f,-161.0f,8.0f,-185.0f,-595.0f,-828.0f,-683.0f, -282.0f,0.0f,-81.0f,-466.0f,-804.0f,-780.0f,-418.0f,-41.0f, 0.0f,-322.0f,-731.0f,-844.0f,-563.0f,-129.0f,40.0f,-185.0f, -627.0f,-876.0f,-699.0f,-249.0f,48.0f,-57.0f,-490.0f,-860.0f, -820.0f,-402.0f,8.0f,48.0f,-330.0f,-796.0f,-908.0f,-563.0f, -73.0f,120.0f,-161.0f,-683.0f,-964.0f,-739.0f,-201.0f,144.0f, 0.0f,-531.0f,-964.0f,-900.0f,-378.0f,120.0f,144.0f,-338.0f, -908.0f,-1037.0f,-587.0f,32.0f,265.0f,-113.0f,-788.0f,-1133.0f, -820.0f,-113.0f,345.0f,120.0f,-603.0f,-1181.0f,-1061.0f,-330.0f, 353.0f,369.0f,-338.0f,-1149.0f,-1310.0f,-635.0f,281.0f,610.0f, 0.0f,-1037.0f,-1551.0f,-1029.0f,104.0f,835.0f,441.0f,-788.0f, -1759.0f,-1534.0f,-217.0f,1036.0f,1036.0f,-338.0f,-1944.0f,-2241.0f, -820.0f,1196.0f,1927.0f,489.0f,-2065.0f,-3446.0f,-2057.0f,1301.0f, 3750.0f,2570.0f,-2153.0f,-6867.0f,-6594.0f,1357.0f,14850.0f,27563.0f, 0 }; t_CKUINT impuls40_size = 256; // data for mand10.raw... SAMPLE mand10_data[] = { 0.0f,224.0f,-73.0f,-611.0f,-474.0f,-1069.0f,-1294.0f,-1671.0f, -1615.0f,128.0f,1060.0f,1212.0f,1525.0f,1815.0f,1060.0f,1301.0f, 1887.0f,1132.0f,674.0f,393.0f,240.0f,216.0f,947.0f,1638.0f, 2072.0f,2441.0f,2080.0f,1774.0f,1670.0f,1076.0f,562.0f,-498.0f, -1623.0f,-1502.0f,-1735.0f,-2129.0f,-2129.0f,-2683.0f,-3494.0f,-3109.0f, -2418.0f,-2386.0f,-2988.0f,-3655.0f,-3864.0f,-3502.0f,-2603.0f,-2795.0f, -2820.0f,-964.0f,514.0f,281.0f,-667.0f,-828.0f,184.0f,1437.0f, 2120.0f,1558.0f,1044.0f,1855.0f,2859.0f,3059.0f,2827.0f,2802.0f, 2786.0f,2819.0f,3276.0f,3887.0f,3798.0f,2859.0f,1983.0f,1694.0f, 1766.0f,1943.0f,1790.0f,955.0f,32.0f,-145.0f,144.0f,827.0f, 1268.0f,771.0f,-81.0f,-1004.0f,-1518.0f,-1655.0f,-2193.0f,-2651.0f, -2836.0f,-2538.0f,-1543.0f,-1149.0f,-1310.0f,-1518.0f,-1808.0f,-2049.0f, -2394.0f,-2651.0f,-2884.0f,-2956.0f,-2554.0f,-1824.0f,-1189.0f,-1157.0f, -1318.0f,-755.0f,321.0f,1164.0f,1469.0f,1389.0f,1501.0f,1670.0f, 1477.0f,1236.0f,714.0f,176.0f,144.0f,353.0f,915.0f,1357.0f, 1445.0f,1453.0f,1421.0f,1566.0f,1959.0f,1847.0f,1437.0f,1301.0f, 1011.0f,722.0f,714.0f,995.0f,1188.0f,867.0f,64.0f,-523.0f, -691.0f,-780.0f,-844.0f,-1157.0f,-1326.0f,-1117.0f,-916.0f,-892.0f, -1077.0f,-1342.0f,-1591.0f,-1703.0f,-1767.0f,-1800.0f,-1767.0f,-1968.0f, -2257.0f,-2185.0f,-1743.0f,-1053.0f,-643.0f,-659.0f,-169.0f,353.0f, 682.0f,1172.0f,1606.0f,2120.0f,2048.0f,1726.0f,1879.0f,2120.0f, 2152.0f,2047.0f,1935.0f,1887.0f,2120.0f,2168.0f,1734.0f,1654.0f, 1871.0f,1638.0f,1309.0f,995.0f,819.0f,787.0f,393.0f,-241.0f, -651.0f,-547.0f,-579.0f,-900.0f,-1037.0f,-1205.0f,-1261.0f,-1213.0f, -1318.0f,-1245.0f,-1318.0f,-1639.0f,-1904.0f,-2008.0f,-1968.0f,-2008.0f, -2065.0f,-2089.0f,-2073.0f,-2105.0f,-2273.0f,-2506.0f,-2394.0f,-2049.0f, -1526.0f,-948.0f,-539.0f,-97.0f,361.0f,586.0f,578.0f,698.0f, 939.0f,1196.0f,1413.0f,1574.0f,1694.0f,1525.0f,1333.0f,1574.0f, 2031.0f,2232.0f,2168.0f,2160.0f,2176.0f,2096.0f,1951.0f,1638.0f, 1333.0f,1156.0f,1011.0f,915.0f,875.0f,803.0f,610.0f,313.0f, 48.0f,-65.0f,-161.0f,-474.0f,-852.0f,-1077.0f,-1197.0f,-1173.0f, -1149.0f,-1101.0f,-1029.0f,-1061.0f,-1069.0f,-1037.0f,-996.0f,-1061.0f, -1237.0f,-1294.0f,-1197.0f,-1189.0f,-1286.0f,-1318.0f,-1061.0f,-595.0f, -241.0f,-9.0f,176.0f,321.0f,377.0f,417.0f,562.0f,730.0f, 754.0f,658.0f,602.0f,690.0f,787.0f,762.0f,690.0f,578.0f, 546.0f,554.0f,546.0f,562.0f,409.0f,224.0f,112.0f,32.0f, 72.0f,64.0f,-81.0f,-225.0f,-282.0f,-274.0f,-274.0f,-346.0f, -474.0f,-547.0f,-515.0f,-474.0f,-498.0f,-523.0f,-555.0f,-579.0f, -555.0f,-539.0f,-506.0f,-531.0f,-547.0f,-442.0f,-314.0f,-201.0f, -153.0f,-137.0f,-65.0f,-33.0f,-81.0f,-41.0f,160.0f,417.0f, 546.0f,562.0f,642.0f,698.0f,698.0f,690.0f,666.0f,666.0f, 738.0f,803.0f,851.0f,899.0f,899.0f,811.0f,706.0f,658.0f, 666.0f,698.0f,706.0f,634.0f,497.0f,281.0f,64.0f,-73.0f, -145.0f,-161.0f,-185.0f,-258.0f,-314.0f,-370.0f,-442.0f,-571.0f, -723.0f,-900.0f,-1045.0f,-1069.0f,-996.0f,-900.0f,-884.0f,-956.0f, -988.0f,-892.0f,-788.0f,-804.0f,-828.0f,-780.0f,-667.0f,-571.0f, -515.0f,-426.0f,-322.0f,-193.0f,-73.0f,24.0f,120.0f,248.0f, 385.0f,489.0f,562.0f,586.0f,594.0f,594.0f,594.0f,642.0f, 674.0f,682.0f,650.0f,618.0f,594.0f,562.0f,522.0f,489.0f, 481.0f,457.0f,449.0f,433.0f,385.0f,337.0f,265.0f,208.0f, 192.0f,176.0f,104.0f,-17.0f,-153.0f,-258.0f,-282.0f,-282.0f, -298.0f,-314.0f,-274.0f,-209.0f,-161.0f,-153.0f,-185.0f,-217.0f, -233.0f,-241.0f,-258.0f,-282.0f,-290.0f,-298.0f,-298.0f,-249.0f, -177.0f,-97.0f,-17.0f,24.0f,56.0f,104.0f,176.0f,248.0f, 257.0f,200.0f,144.0f,144.0f,160.0f,192.0f,200.0f,208.0f, 208.0f,176.0f,136.0f,96.0f,32.0f,-33.0f,-73.0f,-97.0f, -121.0f,-153.0f,-193.0f,-241.0f,-290.0f,-338.0f,-362.0f,-354.0f, -314.0f,-274.0f,-258.0f,-258.0f,-241.0f,-241.0f,-233.0f,-233.0f, -217.0f,-201.0f,-185.0f,-161.0f,-137.0f,-105.0f,-73.0f,-57.0f, -25.0f,24.0f,80.0f,120.0f,168.0f,224.0f,281.0f,313.0f, 321.0f,337.0f,361.0f,369.0f,385.0f,393.0f,417.0f,433.0f, 409.0f,369.0f,337.0f,337.0f,353.0f,385.0f,393.0f,393.0f, 377.0f,345.0f,289.0f,224.0f,160.0f,104.0f,56.0f,8.0f, -25.0f,-81.0f,-145.0f,-209.0f,-258.0f,-290.0f,-314.0f,-314.0f, -306.0f,-314.0f,-354.0f,-410.0f,-450.0f,-474.0f,-474.0f,-458.0f, -450.0f,-434.0f,-410.0f,-386.0f,-346.0f,-306.0f,-282.0f,-266.0f, -241.0f,-209.0f,-153.0f,-105.0f,-65.0f,-17.0f,24.0f,72.0f, 128.0f,184.0f,232.0f,265.0f,281.0f,313.0f,337.0f,361.0f, 361.0f,345.0f,313.0f,297.0f,273.0f,265.0f,240.0f,216.0f, 176.0f,144.0f,112.0f,88.0f,64.0f,40.0f,24.0f,16.0f, 8.0f,-9.0f,-33.0f,-41.0f,-57.0f,-81.0f,-105.0f,-105.0f, -105.0f,-97.0f,-97.0f,-89.0f,-65.0f,-33.0f,-9.0f,0.0f, 24.0f,40.0f,48.0f,48.0f,48.0f,48.0f,56.0f,56.0f, 64.0f,72.0f,72.0f,80.0f,72.0f,64.0f,64.0f,56.0f, 56.0f,64.0f,72.0f,72.0f,72.0f,64.0f,64.0f,80.0f, 88.0f,72.0f,48.0f,16.0f,-1.0f,-25.0f,-65.0f,-105.0f, -145.0f,-177.0f,-185.0f,-185.0f,-193.0f,-217.0f,-225.0f,-225.0f, -217.0f,-209.0f,-209.0f,-209.0f,-217.0f,-209.0f,-185.0f,-161.0f, -145.0f,-137.0f,-129.0f,-121.0f,-97.0f,-65.0f,-33.0f,0.0f, 40.0f,72.0f,104.0f,120.0f,136.0f,160.0f,184.0f,216.0f, 248.0f,265.0f,281.0f,289.0f,289.0f,281.0f,273.0f,265.0f, 257.0f,248.0f,240.0f,224.0f,200.0f,184.0f,168.0f,160.0f, 144.0f,136.0f,128.0f,112.0f,96.0f,80.0f,64.0f,48.0f, 24.0f,-9.0f,-41.0f,-73.0f,-113.0f,-145.0f,-169.0f,-169.0f, -169.0f,-185.0f,-201.0f,-217.0f,-217.0f,-209.0f,-201.0f,-193.0f, -177.0f,-169.0f,-161.0f,-153.0f,-153.0f,-145.0f,-137.0f,-129.0f, -113.0f,-113.0f,-113.0f,-97.0f,-81.0f,-65.0f,-41.0f,-17.0f, 8.0f,48.0f,72.0f,80.0f,88.0f,104.0f,112.0f,120.0f, 120.0f,112.0f,104.0f,96.0f,104.0f,112.0f,120.0f,136.0f, 144.0f,136.0f,120.0f,104.0f,88.0f,88.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 0 }; t_CKUINT mand10_size = 1024; // data for mand11.raw... SAMPLE mand11_data[] = { 0.0f,-177.0f,-531.0f,-723.0f,-908.0f,-1261.0f,-1286.0f,-450.0f, 931.0f,1276.0f,72.0f,-506.0f,514.0f,1758.0f,1525.0f,626.0f, 594.0f,1293.0f,1501.0f,666.0f,216.0f,811.0f,1630.0f,1501.0f, 417.0f,-667.0f,-932.0f,-298.0f,96.0f,-346.0f,-1189.0f,-1165.0f, -9.0f,594.0f,-105.0f,-1350.0f,-2201.0f,-1896.0f,-1037.0f,-282.0f, 200.0f,-651.0f,-1534.0f,-2040.0f,-2225.0f,-1671.0f,-1053.0f,-418.0f, -450.0f,-763.0f,-1053.0f,-563.0f,586.0f,859.0f,329.0f,-121.0f, -129.0f,538.0f,1252.0f,1132.0f,618.0f,538.0f,1100.0f,1694.0f, 1750.0f,971.0f,634.0f,1405.0f,2168.0f,2015.0f,1517.0f,1268.0f, 1244.0f,1116.0f,433.0f,265.0f,819.0f,1550.0f,1196.0f,216.0f, -258.0f,-225.0f,248.0f,144.0f,-394.0f,-900.0f,-844.0f,-515.0f, -450.0f,-683.0f,-1165.0f,-1711.0f,-2161.0f,-1888.0f,-1245.0f,-715.0f, -739.0f,-1197.0f,-1366.0f,-1069.0f,-699.0f,-458.0f,-177.0f,-274.0f, -707.0f,-1117.0f,-1061.0f,-539.0f,-314.0f,-314.0f,-225.0f,104.0f, 449.0f,554.0f,522.0f,385.0f,505.0f,666.0f,674.0f,658.0f, 690.0f,666.0f,682.0f,907.0f,851.0f,497.0f,232.0f,449.0f, 947.0f,1060.0f,722.0f,337.0f,152.0f,216.0f,224.0f,-105.0f, -362.0f,-386.0f,-241.0f,-97.0f,-322.0f,-763.0f,-1029.0f,-763.0f, -515.0f,-699.0f,-1181.0f,-1502.0f,-972.0f,-266.0f,-65.0f,-298.0f, -362.0f,224.0f,843.0f,899.0f,674.0f,449.0f,281.0f,200.0f, 184.0f,216.0f,393.0f,754.0f,987.0f,987.0f,995.0f,1076.0f, 1116.0f,1076.0f,883.0f,562.0f,265.0f,136.0f,152.0f,200.0f, 273.0f,425.0f,401.0f,184.0f,-17.0f,-121.0f,-81.0f,-113.0f, -346.0f,-683.0f,-1045.0f,-1149.0f,-988.0f,-940.0f,-1053.0f,-1181.0f, -1133.0f,-996.0f,-828.0f,-659.0f,-643.0f,-755.0f,-1077.0f,-1286.0f, -1205.0f,-1045.0f,-755.0f,-506.0f,-474.0f,-394.0f,-193.0f,32.0f, 289.0f,305.0f,160.0f,16.0f,56.0f,345.0f,594.0f,530.0f, 240.0f,216.0f,481.0f,795.0f,1011.0f,1019.0f,915.0f,762.0f, 771.0f,891.0f,883.0f,698.0f,514.0f,489.0f,578.0f,738.0f, 690.0f,441.0f,321.0f,393.0f,562.0f,578.0f,329.0f,72.0f, -25.0f,-89.0f,-137.0f,-177.0f,-209.0f,-249.0f,-354.0f,-410.0f, -346.0f,-306.0f,-306.0f,-338.0f,-490.0f,-619.0f,-555.0f,-426.0f, -330.0f,-266.0f,-282.0f,-298.0f,-346.0f,-426.0f,-402.0f,-362.0f, -306.0f,-306.0f,-322.0f,-225.0f,-73.0f,56.0f,-1.0f,-113.0f, -145.0f,-17.0f,176.0f,240.0f,192.0f,96.0f,48.0f,-1.0f, -65.0f,-121.0f,-89.0f,16.0f,112.0f,120.0f,32.0f,-33.0f, -41.0f,0.0f,-9.0f,-89.0f,-177.0f,-185.0f,-121.0f,-97.0f, -145.0f,-193.0f,-177.0f,-137.0f,-161.0f,-177.0f,-105.0f,0.0f, 40.0f,-25.0f,-89.0f,-41.0f,40.0f,80.0f,8.0f,40.0f, 144.0f,248.0f,337.0f,329.0f,329.0f,345.0f,313.0f,281.0f, 345.0f,465.0f,497.0f,441.0f,369.0f,377.0f,409.0f,393.0f, 345.0f,313.0f,305.0f,321.0f,305.0f,232.0f,176.0f,112.0f, 88.0f,112.0f,144.0f,120.0f,56.0f,8.0f,-1.0f,-41.0f, -145.0f,-298.0f,-402.0f,-450.0f,-450.0f,-482.0f,-539.0f,-547.0f, -555.0f,-571.0f,-579.0f,-571.0f,-563.0f,-531.0f,-506.0f,-498.0f, -523.0f,-555.0f,-563.0f,-506.0f,-394.0f,-314.0f,-282.0f,-249.0f, -105.0f,64.0f,136.0f,104.0f,64.0f,80.0f,152.0f,224.0f, 257.0f,265.0f,281.0f,273.0f,273.0f,337.0f,425.0f,481.0f, 481.0f,465.0f,473.0f,489.0f,457.0f,369.0f,248.0f,160.0f, 152.0f,208.0f,289.0f,329.0f,313.0f,265.0f,224.0f,192.0f, 152.0f,88.0f,32.0f,-1.0f,-17.0f,-33.0f,-65.0f,-105.0f, -137.0f,-145.0f,-153.0f,-137.0f,-105.0f,-81.0f,-57.0f,-57.0f, -73.0f,-113.0f,-137.0f,-129.0f,-89.0f,-73.0f,-65.0f,-25.0f, 0.0f,0.0f,-33.0f,-113.0f,-153.0f,-137.0f,-105.0f,-81.0f, -65.0f,-49.0f,-33.0f,-9.0f,-9.0f,-17.0f,-25.0f,-41.0f, -49.0f,-49.0f,-49.0f,-57.0f,-89.0f,-121.0f,-145.0f,-145.0f, -137.0f,-105.0f,-81.0f,-65.0f,-73.0f,-81.0f,-81.0f,-97.0f, -113.0f,-153.0f,-169.0f,-161.0f,-137.0f,-113.0f,-89.0f,-65.0f, -49.0f,-41.0f,-17.0f,16.0f,48.0f,64.0f,72.0f,104.0f, 136.0f,160.0f,184.0f,216.0f,257.0f,289.0f,305.0f,321.0f, 321.0f,321.0f,313.0f,321.0f,337.0f,321.0f,289.0f,265.0f, 257.0f,257.0f,232.0f,184.0f,136.0f,120.0f,120.0f,112.0f, 96.0f,56.0f,24.0f,-1.0f,-33.0f,-49.0f,-65.0f,-89.0f, -113.0f,-145.0f,-177.0f,-217.0f,-258.0f,-290.0f,-298.0f,-298.0f, -282.0f,-258.0f,-225.0f,-201.0f,-193.0f,-201.0f,-217.0f,-225.0f, -217.0f,-201.0f,-177.0f,-161.0f,-145.0f,-137.0f,-113.0f,-89.0f, -65.0f,-49.0f,-33.0f,-9.0f,16.0f,32.0f,24.0f,16.0f, 16.0f,32.0f,48.0f,56.0f,64.0f,88.0f,120.0f,144.0f, 160.0f,160.0f,136.0f,120.0f,112.0f,120.0f,128.0f,120.0f, 112.0f,120.0f,120.0f,128.0f,120.0f,120.0f,120.0f,120.0f, 120.0f,120.0f,112.0f,104.0f,96.0f,80.0f,72.0f,64.0f, 64.0f,64.0f,64.0f,56.0f,40.0f,32.0f,32.0f,32.0f, 32.0f,24.0f,24.0f,16.0f,16.0f,16.0f,24.0f,32.0f, 32.0f,24.0f,8.0f,8.0f,0.0f,0.0f,-17.0f,-49.0f, -65.0f,-81.0f,-97.0f,-105.0f,-121.0f,-129.0f,-137.0f,-137.0f, -137.0f,-145.0f,-153.0f,-169.0f,-169.0f,-169.0f,-161.0f,-153.0f, -145.0f,-129.0f,-105.0f,-81.0f,-65.0f,-41.0f,-25.0f,-1.0f, 0.0f,8.0f,8.0f,0.0f,0.0f,0.0f,16.0f,32.0f, 48.0f,56.0f,56.0f,56.0f,72.0f,96.0f,104.0f,96.0f, 80.0f,80.0f,88.0f,96.0f,104.0f,112.0f,120.0f,136.0f, 144.0f,160.0f,160.0f,144.0f,136.0f,120.0f,112.0f,96.0f, 88.0f,80.0f,72.0f,64.0f,56.0f,48.0f,40.0f,40.0f, 24.0f,8.0f,0.0f,-9.0f,-17.0f,-17.0f,-25.0f,-33.0f, -49.0f,-57.0f,-57.0f,-57.0f,-49.0f,-57.0f,-65.0f,-73.0f, -81.0f,-81.0f,-89.0f,-89.0f,-81.0f,-81.0f,-81.0f,-73.0f, -73.0f,-65.0f,-65.0f,-65.0f,-57.0f,-49.0f,-49.0f,-49.0f, -49.0f,-33.0f,-17.0f,-9.0f,-9.0f,-17.0f,-17.0f,-9.0f, -9.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-9.0f, -9.0f,-9.0f,0.0f,0.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,16.0f,32.0f,48.0f,56.0f,64.0f,72.0f, 72.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f,80.0f, 0 }; t_CKUINT mand11_size = 1024; // data for mand12.raw... SAMPLE mand12_data[] = { 0.0f,224.0f,-836.0f,-1824.0f,-1534.0f,-2651.0f,-3149.0f,-1149.0f, 2048.0f,3734.0f,3814.0f,3011.0f,971.0f,-1.0f,-33.0f,-314.0f, 0.0f,1019.0f,1156.0f,1542.0f,1831.0f,1710.0f,843.0f,-892.0f, -563.0f,-330.0f,610.0f,1309.0f,281.0f,-547.0f,-1518.0f,-1205.0f, 240.0f,795.0f,-739.0f,-1743.0f,-1703.0f,-1663.0f,-1583.0f,-2402.0f, -3093.0f,-2322.0f,-1559.0f,-1478.0f,-675.0f,200.0f,-531.0f,-2579.0f, -3133.0f,-2032.0f,-402.0f,1309.0f,1212.0f,313.0f,337.0f,353.0f, 184.0f,-201.0f,-354.0f,-177.0f,915.0f,2634.0f,3092.0f,2618.0f, 2409.0f,2481.0f,1710.0f,891.0f,1533.0f,2706.0f,3156.0f,2794.0f, 1734.0f,867.0f,369.0f,417.0f,417.0f,192.0f,1036.0f,1718.0f, 1461.0f,562.0f,-410.0f,-1326.0f,-1639.0f,-1181.0f,-1173.0f,-747.0f, 329.0f,321.0f,-402.0f,-1004.0f,-1615.0f,-1631.0f,-1743.0f,-1872.0f, -1446.0f,-868.0f,-972.0f,-1944.0f,-2193.0f,-1743.0f,-1213.0f,-1053.0f, -1374.0f,-1510.0f,-1221.0f,-1205.0f,-1012.0f,-49.0f,353.0f,-282.0f, -1149.0f,-1229.0f,-362.0f,859.0f,1927.0f,2505.0f,2923.0f,2626.0f, 1036.0f,-225.0f,-314.0f,425.0f,1236.0f,1188.0f,329.0f,-25.0f, 602.0f,1260.0f,1076.0f,160.0f,-611.0f,-1141.0f,-691.0f,-274.0f, -306.0f,-89.0f,16.0f,144.0f,80.0f,610.0f,1333.0f,1421.0f, 1076.0f,481.0f,240.0f,554.0f,674.0f,96.0f,-788.0f,-1149.0f, -940.0f,-539.0f,-458.0f,-804.0f,-820.0f,-466.0f,-217.0f,-338.0f, -595.0f,-282.0f,602.0f,1108.0f,971.0f,570.0f,289.0f,457.0f, 963.0f,1228.0f,1293.0f,1397.0f,1469.0f,1341.0f,698.0f,-129.0f, -820.0f,-844.0f,-177.0f,377.0f,417.0f,24.0f,-539.0f,-996.0f, -1117.0f,-1020.0f,-892.0f,-1004.0f,-1061.0f,-555.0f,-41.0f,-49.0f, -378.0f,-836.0f,-1109.0f,-1069.0f,-868.0f,-595.0f,-474.0f,-555.0f, -731.0f,-707.0f,-603.0f,-555.0f,-627.0f,-1020.0f,-1197.0f,-876.0f, -442.0f,-153.0f,88.0f,160.0f,64.0f,32.0f,160.0f,497.0f, 746.0f,618.0f,522.0f,795.0f,1076.0f,1084.0f,955.0f,923.0f, 1108.0f,1373.0f,1493.0f,1461.0f,1437.0f,1389.0f,1252.0f,987.0f, 666.0f,369.0f,160.0f,88.0f,232.0f,457.0f,473.0f,393.0f, 281.0f,168.0f,-81.0f,-555.0f,-908.0f,-972.0f,-796.0f,-523.0f, -410.0f,-410.0f,-282.0f,-225.0f,-370.0f,-482.0f,-386.0f,-322.0f, -466.0f,-603.0f,-707.0f,-900.0f,-1069.0f,-1045.0f,-731.0f,-290.0f, -33.0f,-129.0f,-314.0f,-193.0f,128.0f,232.0f,40.0f,-89.0f, 16.0f,273.0f,313.0f,224.0f,208.0f,224.0f,273.0f,216.0f, 40.0f,-65.0f,-41.0f,-25.0f,0.0f,80.0f,128.0f,128.0f, -1.0f,-145.0f,-137.0f,-113.0f,-81.0f,-33.0f,-33.0f,-81.0f, -97.0f,-113.0f,-161.0f,-201.0f,-185.0f,-1.0f,224.0f,353.0f, 337.0f,232.0f,192.0f,160.0f,128.0f,56.0f,-1.0f,-1.0f, -17.0f,-89.0f,-121.0f,16.0f,265.0f,393.0f,289.0f,192.0f, 265.0f,369.0f,465.0f,481.0f,425.0f,345.0f,281.0f,273.0f, 345.0f,457.0f,489.0f,361.0f,265.0f,297.0f,313.0f,281.0f, 176.0f,112.0f,168.0f,200.0f,152.0f,8.0f,-177.0f,-370.0f, -547.0f,-619.0f,-619.0f,-515.0f,-338.0f,-225.0f,-306.0f,-490.0f, -627.0f,-683.0f,-699.0f,-715.0f,-723.0f,-675.0f,-563.0f,-442.0f, -418.0f,-418.0f,-378.0f,-306.0f,-249.0f,-217.0f,-161.0f,-81.0f, 16.0f,112.0f,192.0f,240.0f,240.0f,248.0f,273.0f,297.0f, 337.0f,417.0f,473.0f,465.0f,361.0f,265.0f,273.0f,369.0f, 473.0f,497.0f,433.0f,385.0f,393.0f,369.0f,265.0f,128.0f, 32.0f,-9.0f,-1.0f,48.0f,104.0f,112.0f,80.0f,32.0f, 24.0f,48.0f,80.0f,120.0f,80.0f,-25.0f,-145.0f,-209.0f, -225.0f,-193.0f,-161.0f,-129.0f,-57.0f,48.0f,152.0f,176.0f, 112.0f,40.0f,24.0f,0.0f,-25.0f,-65.0f,-65.0f,-9.0f, 64.0f,96.0f,64.0f,16.0f,-1.0f,24.0f,80.0f,112.0f, 96.0f,48.0f,16.0f,8.0f,-9.0f,-57.0f,-129.0f,-161.0f, -169.0f,-201.0f,-233.0f,-258.0f,-282.0f,-306.0f,-338.0f,-354.0f, -338.0f,-290.0f,-225.0f,-209.0f,-217.0f,-241.0f,-249.0f,-233.0f, -217.0f,-193.0f,-153.0f,-105.0f,-57.0f,-9.0f,32.0f,80.0f, 128.0f,160.0f,176.0f,184.0f,208.0f,248.0f,265.0f,240.0f, 208.0f,200.0f,208.0f,216.0f,248.0f,289.0f,345.0f,409.0f, 409.0f,369.0f,345.0f,345.0f,353.0f,353.0f,321.0f,273.0f, 224.0f,176.0f,128.0f,112.0f,96.0f,88.0f,80.0f,96.0f, 120.0f,144.0f,136.0f,72.0f,-1.0f,-65.0f,-113.0f,-153.0f, -201.0f,-233.0f,-258.0f,-266.0f,-258.0f,-241.0f,-249.0f,-266.0f, -290.0f,-314.0f,-322.0f,-306.0f,-290.0f,-282.0f,-290.0f,-322.0f, -322.0f,-298.0f,-258.0f,-233.0f,-201.0f,-169.0f,-137.0f,-129.0f, -129.0f,-121.0f,-73.0f,-9.0f,40.0f,64.0f,104.0f,144.0f, 184.0f,192.0f,200.0f,216.0f,248.0f,257.0f,240.0f,232.0f, 240.0f,248.0f,232.0f,216.0f,232.0f,240.0f,208.0f,152.0f, 88.0f,48.0f,40.0f,32.0f,24.0f,32.0f,48.0f,64.0f, 72.0f,72.0f,72.0f,72.0f,64.0f,40.0f,8.0f,-9.0f, -25.0f,-25.0f,-9.0f,8.0f,32.0f,24.0f,8.0f,8.0f, 32.0f,72.0f,96.0f,88.0f,64.0f,48.0f,40.0f,32.0f, 8.0f,-17.0f,-17.0f,0.0f,24.0f,24.0f,8.0f,-9.0f, -17.0f,-17.0f,-17.0f,-17.0f,-17.0f,-25.0f,-41.0f,-65.0f, -89.0f,-105.0f,-121.0f,-129.0f,-137.0f,-145.0f,-161.0f,-161.0f, -161.0f,-153.0f,-129.0f,-121.0f,-137.0f,-161.0f,-169.0f,-145.0f, -121.0f,-105.0f,-97.0f,-81.0f,-65.0f,-65.0f,-57.0f,-41.0f, -17.0f,16.0f,40.0f,56.0f,72.0f,88.0f,104.0f,112.0f, 120.0f,152.0f,184.0f,216.0f,224.0f,232.0f,240.0f,248.0f, 257.0f,273.0f,289.0f,289.0f,289.0f,265.0f,240.0f,216.0f, 184.0f,160.0f,144.0f,128.0f,104.0f,80.0f,56.0f,40.0f, 40.0f,40.0f,32.0f,8.0f,-17.0f,-49.0f,-73.0f,-97.0f, -113.0f,-145.0f,-169.0f,-185.0f,-193.0f,-193.0f,-193.0f,-177.0f, -161.0f,-153.0f,-145.0f,-153.0f,-153.0f,-153.0f,-153.0f,-145.0f, -137.0f,-129.0f,-121.0f,-105.0f,-89.0f,-81.0f,-73.0f,-81.0f, -73.0f,-49.0f,-25.0f,-9.0f,-9.0f,0.0f,24.0f,64.0f, 96.0f,104.0f,120.0f,120.0f,120.0f,120.0f,120.0f,120.0f, 128.0f,128.0f,120.0f,112.0f,112.0f,112.0f,96.0f,88.0f, 80.0f,72.0f,56.0f,48.0f,40.0f,32.0f,32.0f,32.0f, 40.0f,32.0f,32.0f,32.0f,32.0f,24.0f,16.0f,16.0f, 16.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f,8.0f, 0 }; t_CKUINT mand12_size = 1024; // data for mand1.raw... SAMPLE mand1_data[] = { 0.0f,441.0f,-4827.0f,-14441.0f,-12674.0f,-4153.0f,6192.0f,11806.0f, 7075.0f,650.0f,4505.0f,8577.0f,3212.0f,602.0f,2128.0f,3389.0f, 1140.0f,2056.0f,5421.0f,7918.0f,9412.0f,1477.0f,-5606.0f,-6032.0f, -2474.0f,2232.0f,1437.0f,-258.0f,-2956.0f,-4988.0f,-2964.0f,-611.0f, -1470.0f,-3534.0f,-3984.0f,-5309.0f,-4611.0f,-2354.0f,-836.0f,-2105.0f, -6482.0f,-8698.0f,-5422.0f,40.0f,931.0f,-2667.0f,-5133.0f,-4691.0f, -3574.0f,-1567.0f,88.0f,-1229.0f,-2346.0f,-1848.0f,915.0f,4449.0f, 6368.0f,7139.0f,5308.0f,2521.0f,899.0f,2272.0f,6184.0f,8673.0f, 6971.0f,4296.0f,3863.0f,4714.0f,4722.0f,3919.0f,3067.0f,3051.0f, 3798.0f,4907.0f,6545.0f,5011.0f,843.0f,-1157.0f,-217.0f,1582.0f, 1782.0f,-266.0f,-1277.0f,393.0f,2064.0f,-137.0f,-3390.0f,-4249.0f, -3518.0f,-3984.0f,-5213.0f,-4908.0f,-4707.0f,-5333.0f,-6626.0f,-6578.0f, -4747.0f,-3245.0f,-3767.0f,-3542.0f,-2008.0f,-1687.0f,-4233.0f,-6482.0f, -5036.0f,-2434.0f,-1518.0f,-2474.0f,-2129.0f,72.0f,2176.0f,2722.0f, 2867.0f,2208.0f,1011.0f,-121.0f,-619.0f,345.0f,1911.0f,3421.0f, 3565.0f,3590.0f,3405.0f,2963.0f,2867.0f,3341.0f,4786.0f,5316.0f, 3581.0f,1485.0f,1124.0f,2264.0f,2441.0f,-531.0f,-2723.0f,-1559.0f, 1485.0f,3549.0f,2192.0f,-97.0f,-1350.0f,-1125.0f,-258.0f,-466.0f, -739.0f,24.0f,650.0f,1019.0f,682.0f,-796.0f,-1840.0f,-2289.0f, -2040.0f,-1157.0f,-723.0f,-780.0f,-868.0f,-233.0f,313.0f,-17.0f, -579.0f,-563.0f,-330.0f,0.0f,827.0f,1686.0f,1485.0f,-346.0f, -1848.0f,-1832.0f,-346.0f,698.0f,345.0f,-129.0f,152.0f,963.0f, 1148.0f,867.0f,457.0f,-73.0f,-619.0f,-563.0f,-249.0f,80.0f, 240.0f,40.0f,-81.0f,-185.0f,-249.0f,-836.0f,-892.0f,-274.0f, -153.0f,-1077.0f,-2241.0f,-2370.0f,-2121.0f,-1534.0f,-876.0f,-651.0f, -788.0f,-515.0f,281.0f,754.0f,240.0f,-948.0f,-1872.0f,-2016.0f, -1061.0f,-145.0f,152.0f,88.0f,273.0f,642.0f,32.0f,-330.0f, 72.0f,851.0f,1646.0f,1758.0f,1831.0f,2152.0f,2224.0f,1566.0f, 1036.0f,1092.0f,1477.0f,1509.0f,1140.0f,1293.0f,1999.0f,2545.0f, 1999.0f,1108.0f,947.0f,1558.0f,1895.0f,1582.0f,1268.0f,1100.0f, 594.0f,-306.0f,-643.0f,-410.0f,192.0f,546.0f,0.0f,-780.0f, -1093.0f,-860.0f,-715.0f,-844.0f,-1141.0f,-1671.0f,-2057.0f,-1936.0f, -1197.0f,-763.0f,-1390.0f,-2073.0f,-2065.0f,-1599.0f,-1478.0f,-1824.0f, -1976.0f,-1526.0f,-876.0f,-755.0f,-964.0f,-916.0f,-563.0f,-346.0f, -498.0f,-611.0f,-418.0f,-137.0f,-41.0f,-25.0f,232.0f,345.0f, 184.0f,152.0f,481.0f,1156.0f,1734.0f,1919.0f,1782.0f,1550.0f, 1212.0f,891.0f,867.0f,1019.0f,979.0f,497.0f,-9.0f,-1.0f, 489.0f,1028.0f,1196.0f,1100.0f,939.0f,883.0f,779.0f,481.0f, 144.0f,-217.0f,-426.0f,-466.0f,-466.0f,-442.0f,-306.0f,-113.0f, -249.0f,-627.0f,-675.0f,-258.0f,273.0f,489.0f,361.0f,208.0f, 104.0f,88.0f,-1.0f,-298.0f,-362.0f,-121.0f,152.0f,176.0f, 0.0f,16.0f,216.0f,602.0f,851.0f,658.0f,313.0f,136.0f, 248.0f,353.0f,120.0f,-402.0f,-876.0f,-972.0f,-667.0f,-314.0f, -153.0f,-89.0f,32.0f,192.0f,208.0f,64.0f,-233.0f,-474.0f, -651.0f,-804.0f,-852.0f,-852.0f,-788.0f,-739.0f,-659.0f,-571.0f, -643.0f,-796.0f,-844.0f,-820.0f,-691.0f,-523.0f,-386.0f,-290.0f, -177.0f,-137.0f,-282.0f,-330.0f,-193.0f,-49.0f,-49.0f,-105.0f, 32.0f,337.0f,642.0f,819.0f,827.0f,787.0f,867.0f,1019.0f, 1140.0f,1196.0f,1156.0f,1019.0f,867.0f,779.0f,819.0f,883.0f, 899.0f,835.0f,730.0f,706.0f,859.0f,1028.0f,1003.0f,811.0f, 522.0f,313.0f,192.0f,88.0f,16.0f,-1.0f,-25.0f,-89.0f, -137.0f,-233.0f,-378.0f,-506.0f,-587.0f,-611.0f,-667.0f,-731.0f, -780.0f,-796.0f,-828.0f,-868.0f,-892.0f,-876.0f,-796.0f,-715.0f, -659.0f,-611.0f,-571.0f,-515.0f,-426.0f,-322.0f,-177.0f,-33.0f, 24.0f,24.0f,-17.0f,-73.0f,-137.0f,-233.0f,-322.0f,-346.0f, -322.0f,-274.0f,-201.0f,-73.0f,168.0f,401.0f,505.0f,457.0f, 361.0f,281.0f,176.0f,56.0f,-1.0f,32.0f,104.0f,136.0f, 160.0f,216.0f,313.0f,393.0f,409.0f,361.0f,329.0f,329.0f, 353.0f,361.0f,337.0f,265.0f,152.0f,80.0f,104.0f,216.0f, 297.0f,273.0f,160.0f,120.0f,208.0f,337.0f,409.0f,361.0f, 257.0f,200.0f,248.0f,321.0f,345.0f,329.0f,289.0f,257.0f, 265.0f,297.0f,321.0f,281.0f,192.0f,120.0f,56.0f,-1.0f, -65.0f,-137.0f,-225.0f,-314.0f,-362.0f,-370.0f,-362.0f,-346.0f, -338.0f,-306.0f,-266.0f,-274.0f,-338.0f,-386.0f,-370.0f,-346.0f, -426.0f,-579.0f,-675.0f,-659.0f,-587.0f,-547.0f,-515.0f,-458.0f, -378.0f,-338.0f,-354.0f,-370.0f,-362.0f,-306.0f,-217.0f,-145.0f, -105.0f,-65.0f,-17.0f,64.0f,200.0f,273.0f,257.0f,208.0f, 216.0f,305.0f,385.0f,369.0f,305.0f,281.0f,337.0f,441.0f, 546.0f,602.0f,610.0f,578.0f,538.0f,505.0f,522.0f,578.0f, 602.0f,538.0f,433.0f,369.0f,393.0f,441.0f,457.0f,385.0f, 265.0f,168.0f,136.0f,136.0f,104.0f,48.0f,24.0f,24.0f, 32.0f,8.0f,-49.0f,-113.0f,-177.0f,-233.0f,-298.0f,-354.0f, -378.0f,-386.0f,-394.0f,-418.0f,-434.0f,-466.0f,-458.0f,-410.0f, -338.0f,-282.0f,-274.0f,-290.0f,-282.0f,-249.0f,-185.0f,-113.0f, -81.0f,-113.0f,-169.0f,-209.0f,-193.0f,-153.0f,-121.0f,-89.0f, -65.0f,-49.0f,-33.0f,-25.0f,-1.0f,32.0f,80.0f,112.0f, 96.0f,72.0f,48.0f,40.0f,48.0f,56.0f,40.0f,32.0f, 56.0f,136.0f,208.0f,216.0f,168.0f,104.0f,96.0f,136.0f, 168.0f,144.0f,120.0f,112.0f,136.0f,184.0f,240.0f,305.0f, 345.0f,337.0f,297.0f,265.0f,248.0f,248.0f,224.0f,184.0f, 120.0f,72.0f,56.0f,72.0f,112.0f,152.0f,176.0f,184.0f, 184.0f,184.0f,176.0f,144.0f,104.0f,80.0f,56.0f,32.0f, -9.0f,-65.0f,-113.0f,-153.0f,-177.0f,-185.0f,-169.0f,-145.0f, -113.0f,-81.0f,-89.0f,-113.0f,-153.0f,-177.0f,-193.0f,-201.0f, -217.0f,-249.0f,-290.0f,-306.0f,-306.0f,-274.0f,-241.0f,-209.0f, -201.0f,-201.0f,-201.0f,-177.0f,-145.0f,-113.0f,-105.0f,-113.0f, -113.0f,-81.0f,-33.0f,16.0f,56.0f,80.0f,96.0f,112.0f, 128.0f,144.0f,152.0f,160.0f,160.0f,160.0f,176.0f,208.0f, 240.0f,257.0f,248.0f,240.0f,248.0f,273.0f,297.0f,297.0f, 297.0f,281.0f,265.0f,265.0f,273.0f,273.0f,257.0f,216.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f,200.0f, 0 }; t_CKUINT mand1_size = 1024; // data for mand2.raw... SAMPLE mand2_data[] = { 0.0f,-65.0f,-844.0f,-1952.0f,-4394.0f,-4514.0f,-2611.0f,-1294.0f, 1204.0f,1638.0f,-563.0f,1975.0f,5268.0f,7445.0f,7083.0f,-9.0f, -2811.0f,-402.0f,4666.0f,6240.0f,3092.0f,-249.0f,216.0f,4224.0f, 2915.0f,-1181.0f,-2980.0f,-2105.0f,-2924.0f,-2571.0f,104.0f,505.0f, -1334.0f,-2193.0f,-3189.0f,-4097.0f,-2860.0f,-2964.0f,-4410.0f,-4289.0f, -2209.0f,-1414.0f,-539.0f,-2354.0f,-4763.0f,-3173.0f,-1647.0f,-1053.0f, -1663.0f,-2595.0f,-1679.0f,578.0f,1124.0f,465.0f,827.0f,2433.0f, 3782.0f,2802.0f,674.0f,867.0f,3148.0f,5276.0f,5067.0f,4762.0f, 4047.0f,2545.0f,3590.0f,3357.0f,3172.0f,3027.0f,2377.0f,3236.0f, 3381.0f,2521.0f,618.0f,-587.0f,1028.0f,3084.0f,2602.0f,746.0f, -1221.0f,-1334.0f,-354.0f,-515.0f,216.0f,393.0f,-1952.0f,-4097.0f, -3856.0f,-2450.0f,-2306.0f,-3783.0f,-4667.0f,-3165.0f,-1358.0f,-1599.0f, -3245.0f,-3831.0f,-3558.0f,-3454.0f,-2747.0f,-2482.0f,-2145.0f,-2129.0f, -1783.0f,-1711.0f,-2546.0f,-2201.0f,-1575.0f,-458.0f,658.0f,666.0f, 891.0f,1847.0f,2224.0f,2264.0f,1381.0f,995.0f,819.0f,160.0f, 915.0f,2240.0f,3598.0f,3702.0f,3670.0f,3212.0f,2240.0f,2465.0f, 2160.0f,1807.0f,1879.0f,1349.0f,899.0f,811.0f,1140.0f,1212.0f, 771.0f,232.0f,-731.0f,-1085.0f,152.0f,1373.0f,1453.0f,674.0f, -1069.0f,-1687.0f,-1020.0f,-498.0f,-924.0f,-2073.0f,-1944.0f,-571.0f, 570.0f,32.0f,-1181.0f,-1422.0f,-884.0f,-1109.0f,-1679.0f,-1526.0f, -828.0f,465.0f,674.0f,-113.0f,-274.0f,-201.0f,-458.0f,-547.0f, -378.0f,80.0f,337.0f,112.0f,-298.0f,-426.0f,-81.0f,104.0f, 216.0f,554.0f,971.0f,1060.0f,706.0f,538.0f,811.0f,754.0f, -1.0f,-747.0f,-643.0f,-217.0f,160.0f,417.0f,425.0f,433.0f, 16.0f,-378.0f,-506.0f,-274.0f,32.0f,-33.0f,-482.0f,-964.0f, -1053.0f,-1020.0f,-635.0f,-193.0f,-249.0f,-900.0f,-1109.0f,-362.0f, 128.0f,-177.0f,-956.0f,-1454.0f,-1181.0f,-547.0f,-25.0f,586.0f, 851.0f,843.0f,803.0f,497.0f,650.0f,1260.0f,1622.0f,1630.0f, 1429.0f,1285.0f,1293.0f,955.0f,570.0f,666.0f,987.0f,1309.0f, 1268.0f,1108.0f,1293.0f,1469.0f,1333.0f,843.0f,224.0f,-41.0f, 32.0f,184.0f,369.0f,361.0f,128.0f,-209.0f,-755.0f,-1037.0f, -972.0f,-812.0f,-707.0f,-1012.0f,-1334.0f,-1004.0f,-531.0f,-611.0f, -1277.0f,-1816.0f,-1623.0f,-1205.0f,-1117.0f,-1237.0f,-1261.0f,-1189.0f, -964.0f,-860.0f,-1037.0f,-884.0f,-490.0f,-169.0f,88.0f,224.0f, 425.0f,449.0f,313.0f,176.0f,200.0f,385.0f,345.0f,192.0f, 248.0f,481.0f,754.0f,931.0f,787.0f,642.0f,738.0f,875.0f, 971.0f,1068.0f,979.0f,690.0f,369.0f,88.0f,120.0f,425.0f, 714.0f,746.0f,698.0f,730.0f,835.0f,947.0f,754.0f,353.0f, 40.0f,-41.0f,56.0f,48.0f,-105.0f,-241.0f,-394.0f,-571.0f, -675.0f,-723.0f,-555.0f,-266.0f,-25.0f,-153.0f,-539.0f,-571.0f, -370.0f,-282.0f,-370.0f,-450.0f,-330.0f,-145.0f,-81.0f,-81.0f, -105.0f,-97.0f,-97.0f,-153.0f,-57.0f,168.0f,329.0f,353.0f, 281.0f,273.0f,345.0f,297.0f,144.0f,8.0f,-1.0f,40.0f, 8.0f,-41.0f,-49.0f,-81.0f,-105.0f,-105.0f,-169.0f,-161.0f, -105.0f,-89.0f,-57.0f,-137.0f,-258.0f,-346.0f,-490.0f,-587.0f, -611.0f,-474.0f,-193.0f,-9.0f,-41.0f,-137.0f,-137.0f,-33.0f, -25.0f,-153.0f,-185.0f,-57.0f,64.0f,40.0f,-57.0f,-65.0f, 40.0f,176.0f,240.0f,297.0f,433.0f,618.0f,706.0f,754.0f, 754.0f,682.0f,570.0f,465.0f,457.0f,489.0f,449.0f,353.0f, 265.0f,248.0f,313.0f,433.0f,489.0f,417.0f,305.0f,216.0f, 224.0f,321.0f,321.0f,152.0f,-81.0f,-233.0f,-266.0f,-282.0f, -290.0f,-274.0f,-209.0f,-209.0f,-290.0f,-282.0f,-274.0f,-330.0f, -474.0f,-571.0f,-523.0f,-426.0f,-426.0f,-498.0f,-506.0f,-434.0f, -410.0f,-458.0f,-450.0f,-362.0f,-225.0f,-169.0f,-185.0f,-137.0f, -25.0f,88.0f,128.0f,112.0f,120.0f,120.0f,80.0f,24.0f, 16.0f,72.0f,152.0f,184.0f,168.0f,144.0f,160.0f,184.0f, 176.0f,168.0f,168.0f,200.0f,192.0f,128.0f,8.0f,-65.0f, -57.0f,0.0f,64.0f,104.0f,160.0f,216.0f,289.0f,353.0f, 377.0f,369.0f,313.0f,208.0f,176.0f,232.0f,273.0f,240.0f, 152.0f,96.0f,136.0f,200.0f,208.0f,152.0f,72.0f,40.0f, 32.0f,48.0f,56.0f,72.0f,56.0f,-1.0f,-65.0f,-65.0f, -33.0f,-1.0f,-1.0f,-49.0f,-89.0f,-121.0f,-121.0f,-97.0f, -73.0f,-65.0f,-73.0f,-81.0f,-81.0f,-73.0f,-89.0f,-121.0f, -201.0f,-298.0f,-322.0f,-306.0f,-274.0f,-266.0f,-290.0f,-290.0f, -249.0f,-217.0f,-225.0f,-249.0f,-241.0f,-225.0f,-217.0f,-217.0f, -185.0f,-121.0f,-49.0f,-17.0f,-25.0f,-17.0f,24.0f,64.0f, 96.0f,128.0f,168.0f,200.0f,208.0f,176.0f,152.0f,144.0f, 144.0f,176.0f,208.0f,257.0f,289.0f,305.0f,321.0f,345.0f, 353.0f,329.0f,281.0f,248.0f,248.0f,273.0f,289.0f,248.0f, 184.0f,128.0f,112.0f,128.0f,136.0f,120.0f,96.0f,72.0f, 48.0f,24.0f,8.0f,-1.0f,-17.0f,-41.0f,-57.0f,-57.0f, -49.0f,-49.0f,-73.0f,-105.0f,-121.0f,-145.0f,-185.0f,-217.0f, -225.0f,-217.0f,-209.0f,-233.0f,-249.0f,-233.0f,-193.0f,-161.0f, -177.0f,-193.0f,-193.0f,-161.0f,-129.0f,-113.0f,-129.0f,-153.0f, -161.0f,-137.0f,-97.0f,-41.0f,0.0f,24.0f,40.0f,40.0f, 32.0f,24.0f,32.0f,56.0f,64.0f,56.0f,56.0f,64.0f, 80.0f,96.0f,112.0f,120.0f,120.0f,104.0f,104.0f,112.0f, 120.0f,112.0f,104.0f,112.0f,136.0f,160.0f,160.0f,160.0f, 152.0f,144.0f,128.0f,104.0f,104.0f,120.0f,128.0f,112.0f, 96.0f,96.0f,104.0f,104.0f,80.0f,48.0f,16.0f,0.0f, -1.0f,0.0f,8.0f,16.0f,16.0f,8.0f,0.0f,0.0f, 0.0f,16.0f,24.0f,16.0f,8.0f,-9.0f,-33.0f,-57.0f, -57.0f,-57.0f,-57.0f,-65.0f,-73.0f,-73.0f,-65.0f,-65.0f, -65.0f,-65.0f,-65.0f,-49.0f,-33.0f,-25.0f,-33.0f,-49.0f, -65.0f,-73.0f,-81.0f,-73.0f,-73.0f,-73.0f,-81.0f,-89.0f, -81.0f,-65.0f,-49.0f,-41.0f,-33.0f,-41.0f,-49.0f,-57.0f, -57.0f,-33.0f,-1.0f,0.0f,0.0f,0.0f,24.0f,64.0f, 104.0f,128.0f,128.0f,128.0f,144.0f,168.0f,184.0f,192.0f, 192.0f,184.0f,176.0f,184.0f,192.0f,184.0f,168.0f,144.0f, 136.0f,136.0f,136.0f,128.0f,112.0f,88.0f,72.0f,64.0f, 64.0f,56.0f,48.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 0 }; t_CKUINT mand2_size = 1024; // data for mand3.raw... SAMPLE mand3_data[] = { 0.0f,-161.0f,-515.0f,-418.0f,96.0f,706.0f,489.0f,393.0f, 168.0f,867.0f,-362.0f,-2346.0f,-4859.0f,-5486.0f,-4723.0f,-6257.0f, 803.0f,9750.0f,12296.0f,4626.0f,-3968.0f,-3221.0f,1766.0f,3565.0f, -161.0f,-1920.0f,-1390.0f,2080.0f,1871.0f,-49.0f,-193.0f,1285.0f, 5276.0f,6216.0f,5694.0f,5999.0f,4015.0f,-691.0f,-2217.0f,-1205.0f, -3165.0f,-6458.0f,-4225.0f,2562.0f,6095.0f,530.0f,-7678.0f,-7678.0f, -1775.0f,738.0f,-2322.0f,-5855.0f,-6345.0f,-5309.0f,-6410.0f,-7197.0f, -4032.0f,-506.0f,-1880.0f,-3952.0f,-2137.0f,152.0f,265.0f,-2000.0f, -2129.0f,297.0f,658.0f,40.0f,120.0f,2762.0f,7300.0f,8665.0f, 7533.0f,4601.0f,2337.0f,3076.0f,3573.0f,4537.0f,4417.0f,2521.0f, 1598.0f,2377.0f,4634.0f,5951.0f,6240.0f,5340.0f,4867.0f,5132.0f, 3252.0f,208.0f,-1133.0f,-490.0f,-1470.0f,-3077.0f,-3117.0f,-860.0f, 779.0f,-651.0f,-1775.0f,-2048.0f,-1237.0f,-1093.0f,-2241.0f,-3848.0f, -5213.0f,-6265.0f,-8048.0f,-8192.0f,-7237.0f,-5125.0f,-3783.0f,-4787.0f, -5341.0f,-3936.0f,-820.0f,851.0f,514.0f,-1494.0f,-2659.0f,-1719.0f, -523.0f,1790.0f,3413.0f,3027.0f,2296.0f,2851.0f,4867.0f,5389.0f, 3292.0f,1598.0f,1582.0f,2305.0f,2513.0f,1590.0f,1036.0f,1967.0f, 3397.0f,3381.0f,2023.0f,1172.0f,1260.0f,1574.0f,1260.0f,562.0f, -354.0f,-1310.0f,-1261.0f,-739.0f,-121.0f,-129.0f,-1069.0f,-1607.0f, -1470.0f,-908.0f,-1181.0f,-1735.0f,-924.0f,160.0f,409.0f,-844.0f, -2643.0f,-2844.0f,-1655.0f,-450.0f,-161.0f,-531.0f,-603.0f,160.0f, 1196.0f,1325.0f,56.0f,-1334.0f,-1430.0f,-81.0f,1774.0f,2473.0f, 1807.0f,1285.0f,1694.0f,2208.0f,2184.0f,1477.0f,1325.0f,2144.0f, 2650.0f,2296.0f,1180.0f,176.0f,-1.0f,104.0f,-81.0f,-603.0f, -555.0f,112.0f,650.0f,762.0f,160.0f,-675.0f,-1615.0f,-2410.0f, -2779.0f,-2546.0f,-1543.0f,-747.0f,-892.0f,-1735.0f,-2281.0f,-2225.0f, -2257.0f,-2354.0f,-2595.0f,-2675.0f,-2137.0f,-1518.0f,-1061.0f,-1053.0f, -1350.0f,-1639.0f,-1824.0f,-1615.0f,-1157.0f,-450.0f,224.0f,851.0f, 1582.0f,1991.0f,2031.0f,1517.0f,1293.0f,1782.0f,2160.0f,2224.0f, 1983.0f,2056.0f,2537.0f,2907.0f,2698.0f,2305.0f,2377.0f,2489.0f, 2305.0f,1895.0f,1590.0f,1614.0f,1710.0f,1341.0f,754.0f,441.0f, 441.0f,626.0f,417.0f,-49.0f,-691.0f,-1470.0f,-1719.0f,-1318.0f, -788.0f,-539.0f,-579.0f,-804.0f,-964.0f,-1093.0f,-1350.0f,-1607.0f, -1647.0f,-1494.0f,-1390.0f,-1358.0f,-1334.0f,-1382.0f,-1526.0f,-1687.0f, -1679.0f,-1350.0f,-852.0f,-426.0f,-241.0f,-161.0f,-121.0f,-233.0f, -482.0f,-643.0f,-418.0f,80.0f,570.0f,803.0f,899.0f,915.0f, 915.0f,931.0f,955.0f,931.0f,851.0f,738.0f,706.0f,803.0f, 867.0f,706.0f,281.0f,8.0f,16.0f,216.0f,489.0f,626.0f, 642.0f,554.0f,337.0f,-129.0f,-723.0f,-1205.0f,-1358.0f,-1101.0f, -659.0f,-153.0f,240.0f,361.0f,208.0f,-137.0f,-466.0f,-595.0f, -458.0f,-161.0f,72.0f,208.0f,321.0f,321.0f,168.0f,-41.0f, -193.0f,-41.0f,361.0f,722.0f,819.0f,746.0f,650.0f,634.0f, 714.0f,730.0f,618.0f,530.0f,562.0f,746.0f,971.0f,1011.0f, 803.0f,449.0f,184.0f,96.0f,16.0f,-177.0f,-338.0f,-290.0f, -129.0f,-65.0f,-129.0f,-145.0f,-137.0f,-241.0f,-386.0f,-515.0f, -555.0f,-571.0f,-731.0f,-996.0f,-1221.0f,-1334.0f,-1286.0f,-980.0f, -515.0f,-217.0f,-233.0f,-458.0f,-635.0f,-683.0f,-804.0f,-956.0f, -980.0f,-876.0f,-691.0f,-571.0f,-515.0f,-434.0f,-258.0f,-33.0f, 184.0f,425.0f,594.0f,610.0f,514.0f,449.0f,457.0f,489.0f, 530.0f,658.0f,851.0f,1036.0f,1124.0f,1100.0f,1084.0f,1052.0f, 971.0f,931.0f,1003.0f,1044.0f,963.0f,762.0f,546.0f,457.0f, 433.0f,345.0f,136.0f,-33.0f,-57.0f,-17.0f,16.0f,8.0f, -1.0f,-33.0f,-129.0f,-290.0f,-442.0f,-458.0f,-378.0f,-274.0f, -258.0f,-386.0f,-563.0f,-675.0f,-667.0f,-603.0f,-539.0f,-474.0f, -362.0f,-193.0f,-81.0f,-41.0f,-57.0f,-97.0f,-153.0f,-225.0f, -290.0f,-274.0f,-193.0f,-121.0f,-81.0f,-73.0f,-81.0f,-65.0f, 0.0f,104.0f,144.0f,56.0f,-65.0f,-105.0f,-25.0f,72.0f, 112.0f,80.0f,24.0f,0.0f,0.0f,-25.0f,-89.0f,-161.0f, -201.0f,-209.0f,-177.0f,-129.0f,-65.0f,0.0f,64.0f,48.0f, -33.0f,-121.0f,-145.0f,-97.0f,0.0f,64.0f,128.0f,192.0f, 208.0f,200.0f,200.0f,224.0f,273.0f,313.0f,305.0f,297.0f, 337.0f,401.0f,441.0f,441.0f,409.0f,401.0f,433.0f,489.0f, 538.0f,554.0f,546.0f,497.0f,417.0f,337.0f,289.0f,281.0f, 265.0f,224.0f,128.0f,40.0f,-1.0f,-41.0f,-113.0f,-225.0f, -330.0f,-370.0f,-346.0f,-290.0f,-241.0f,-241.0f,-306.0f,-410.0f, -506.0f,-547.0f,-563.0f,-571.0f,-587.0f,-579.0f,-579.0f,-587.0f, -595.0f,-539.0f,-418.0f,-290.0f,-225.0f,-201.0f,-177.0f,-121.0f, -65.0f,-65.0f,-105.0f,-161.0f,-169.0f,-113.0f,-9.0f,88.0f, 176.0f,232.0f,257.0f,257.0f,232.0f,192.0f,152.0f,144.0f, 144.0f,168.0f,232.0f,321.0f,401.0f,441.0f,433.0f,425.0f, 425.0f,417.0f,409.0f,401.0f,377.0f,337.0f,273.0f,216.0f, 200.0f,216.0f,224.0f,200.0f,144.0f,88.0f,64.0f,48.0f, 32.0f,0.0f,-41.0f,-97.0f,-137.0f,-161.0f,-153.0f,-137.0f, -113.0f,-105.0f,-97.0f,-113.0f,-121.0f,-121.0f,-97.0f,-57.0f, -33.0f,-33.0f,-41.0f,-41.0f,-33.0f,-49.0f,-65.0f,-89.0f, -97.0f,-81.0f,-65.0f,-49.0f,-57.0f,-73.0f,-97.0f,-105.0f, -113.0f,-121.0f,-145.0f,-153.0f,-161.0f,-169.0f,-161.0f,-121.0f, -73.0f,-49.0f,-73.0f,-129.0f,-185.0f,-193.0f,-177.0f,-153.0f, -145.0f,-153.0f,-169.0f,-169.0f,-153.0f,-121.0f,-81.0f,-33.0f, -1.0f,24.0f,48.0f,80.0f,112.0f,144.0f,176.0f,208.0f, 224.0f,240.0f,265.0f,281.0f,281.0f,273.0f,265.0f,257.0f, 265.0f,281.0f,273.0f,257.0f,240.0f,240.0f,273.0f,305.0f, 321.0f,289.0f,232.0f,168.0f,128.0f,112.0f,112.0f,112.0f, 96.0f,72.0f,48.0f,24.0f,0.0f,-9.0f,-25.0f,-49.0f, -73.0f,-113.0f,-161.0f,-185.0f,-193.0f,-185.0f,-177.0f,-201.0f, -233.0f,-274.0f,-290.0f,-290.0f,-290.0f,-298.0f,-298.0f,-290.0f, -258.0f,-233.0f,-217.0f,-209.0f,-185.0f,-145.0f,-121.0f,-97.0f, -89.0f,-73.0f,-73.0f,-65.0f,-49.0f,-9.0f,48.0f,96.0f, 120.0f,120.0f,96.0f,72.0f,72.0f,88.0f,104.0f,104.0f, 88.0f,88.0f,112.0f,160.0f,184.0f,224.0f,208.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f,224.0f, 0 }; t_CKUINT mand3_size = 1024; // data for mand4.raw... SAMPLE mand4_data[] = { 0.0f,-145.0f,-73.0f,-1109.0f,-2892.0f,-2860.0f,-2121.0f,-1743.0f, -2378.0f,-2956.0f,-2434.0f,554.0f,4497.0f,7332.0f,5862.0f,698.0f, -1703.0f,3236.0f,10336.0f,8569.0f,321.0f,-4345.0f,-1141.0f,4923.0f, 7621.0f,3324.0f,-3390.0f,-5189.0f,-2892.0f,-129.0f,-1004.0f,-3534.0f, -1832.0f,-763.0f,-4458.0f,-5261.0f,-2811.0f,216.0f,1260.0f,-2217.0f, -5133.0f,-5936.0f,-3679.0f,-868.0f,-1350.0f,-2169.0f,-4627.0f,-4980.0f, -2281.0f,-490.0f,1060.0f,-394.0f,-1470.0f,-755.0f,819.0f,3204.0f, 3212.0f,1582.0f,1164.0f,2305.0f,3019.0f,3381.0f,3573.0f,4136.0f, 3790.0f,2682.0f,2048.0f,3188.0f,5381.0f,5236.0f,3284.0f,746.0f, 843.0f,2698.0f,3959.0f,4425.0f,2642.0f,666.0f,-217.0f,48.0f, 1244.0f,883.0f,-1671.0f,-3719.0f,-3277.0f,-1366.0f,-370.0f,-1639.0f, -3655.0f,-4739.0f,-3856.0f,-2418.0f,-1848.0f,-1759.0f,-2346.0f,-2386.0f, -1751.0f,-1029.0f,-1583.0f,-3028.0f,-3599.0f,-3117.0f,-1591.0f,-876.0f, -1221.0f,-1615.0f,-1936.0f,-1880.0f,-1414.0f,-266.0f,473.0f,465.0f, 208.0f,200.0f,1188.0f,1726.0f,1638.0f,1718.0f,1477.0f,1276.0f, 1244.0f,2321.0f,3670.0f,3196.0f,1927.0f,1084.0f,1678.0f,2570.0f, 2473.0f,2064.0f,1646.0f,915.0f,650.0f,1614.0f,1855.0f,803.0f, -346.0f,-1358.0f,-1286.0f,-651.0f,-627.0f,-884.0f,-1575.0f,-2040.0f, -1920.0f,-1856.0f,-1647.0f,-1012.0f,-498.0f,-482.0f,-1077.0f,-1735.0f, -1430.0f,-619.0f,-266.0f,-731.0f,-1045.0f,-426.0f,915.0f,1935.0f, 1493.0f,369.0f,-137.0f,297.0f,1140.0f,1614.0f,1742.0f,1718.0f, 915.0f,160.0f,192.0f,505.0f,690.0f,481.0f,489.0f,666.0f, 762.0f,939.0f,1140.0f,771.0f,-233.0f,-1061.0f,-940.0f,281.0f, 1003.0f,441.0f,-731.0f,-1374.0f,-1045.0f,-611.0f,-587.0f,-1430.0f, -2209.0f,-2040.0f,-1310.0f,-820.0f,-1037.0f,-1623.0f,-1687.0f,-1004.0f, -450.0f,-683.0f,-1061.0f,-844.0f,-354.0f,-153.0f,-587.0f,-1061.0f, -812.0f,-274.0f,136.0f,329.0f,361.0f,730.0f,1188.0f,1124.0f, 859.0f,787.0f,1116.0f,1550.0f,1429.0f,1108.0f,987.0f,1100.0f, 1373.0f,1349.0f,1180.0f,1060.0f,1076.0f,1445.0f,1750.0f,1421.0f, 666.0f,176.0f,289.0f,666.0f,754.0f,514.0f,144.0f,-121.0f, -249.0f,-434.0f,-635.0f,-780.0f,-731.0f,-772.0f,-956.0f,-1037.0f, -988.0f,-940.0f,-940.0f,-1020.0f,-1141.0f,-1085.0f,-739.0f,-306.0f, -217.0f,-386.0f,-531.0f,-354.0f,-65.0f,-81.0f,-434.0f,-820.0f, -587.0f,184.0f,811.0f,658.0f,64.0f,-282.0f,-97.0f,232.0f, 144.0f,-89.0f,-306.0f,-298.0f,96.0f,481.0f,505.0f,152.0f, -225.0f,-225.0f,-25.0f,184.0f,377.0f,417.0f,297.0f,136.0f, -9.0f,0.0f,176.0f,265.0f,160.0f,-33.0f,-17.0f,224.0f, 353.0f,265.0f,72.0f,-201.0f,-386.0f,-338.0f,-105.0f,72.0f, 96.0f,104.0f,152.0f,257.0f,313.0f,240.0f,104.0f,40.0f, 80.0f,144.0f,136.0f,136.0f,136.0f,80.0f,-33.0f,-113.0f, -1.0f,240.0f,473.0f,505.0f,457.0f,409.0f,265.0f,184.0f, 192.0f,104.0f,-25.0f,-17.0f,208.0f,385.0f,361.0f,160.0f, -25.0f,-41.0f,64.0f,120.0f,-57.0f,-346.0f,-474.0f,-426.0f, -314.0f,-225.0f,-249.0f,-362.0f,-515.0f,-603.0f,-627.0f,-627.0f, -579.0f,-611.0f,-699.0f,-659.0f,-466.0f,-201.0f,-73.0f,-201.0f, -370.0f,-314.0f,-17.0f,257.0f,232.0f,0.0f,-137.0f,-41.0f, 168.0f,224.0f,96.0f,-17.0f,16.0f,168.0f,265.0f,297.0f, 257.0f,265.0f,353.0f,393.0f,337.0f,192.0f,144.0f,257.0f, 361.0f,393.0f,329.0f,216.0f,176.0f,257.0f,321.0f,273.0f, 216.0f,240.0f,321.0f,337.0f,265.0f,160.0f,64.0f,56.0f, 112.0f,160.0f,184.0f,208.0f,224.0f,176.0f,56.0f,-73.0f, -153.0f,-161.0f,-177.0f,-217.0f,-249.0f,-266.0f,-233.0f,-233.0f, -258.0f,-266.0f,-233.0f,-161.0f,-129.0f,-145.0f,-129.0f,-81.0f, -41.0f,-81.0f,-169.0f,-241.0f,-233.0f,-121.0f,-25.0f,-9.0f, -41.0f,-49.0f,-1.0f,24.0f,8.0f,-33.0f,-121.0f,-169.0f, -161.0f,-129.0f,-89.0f,-81.0f,-65.0f,-49.0f,-17.0f,0.0f, -41.0f,-97.0f,-137.0f,-137.0f,-81.0f,-57.0f,-49.0f,-57.0f, -41.0f,16.0f,104.0f,160.0f,144.0f,56.0f,0.0f,48.0f, 176.0f,273.0f,281.0f,224.0f,208.0f,281.0f,385.0f,425.0f, 329.0f,192.0f,152.0f,200.0f,273.0f,281.0f,192.0f,80.0f, 48.0f,104.0f,176.0f,224.0f,216.0f,160.0f,88.0f,40.0f, 16.0f,-1.0f,-25.0f,-41.0f,-49.0f,-57.0f,-73.0f,-73.0f, -49.0f,-17.0f,-25.0f,-41.0f,-49.0f,-17.0f,16.0f,8.0f, -49.0f,-121.0f,-153.0f,-137.0f,-137.0f,-177.0f,-241.0f,-290.0f, -306.0f,-298.0f,-306.0f,-306.0f,-322.0f,-330.0f,-298.0f,-249.0f, -201.0f,-161.0f,-129.0f,-105.0f,-65.0f,-33.0f,-9.0f,-1.0f, -1.0f,8.0f,48.0f,104.0f,144.0f,136.0f,96.0f,88.0f, 136.0f,184.0f,208.0f,184.0f,160.0f,136.0f,128.0f,144.0f, 176.0f,192.0f,208.0f,208.0f,208.0f,208.0f,200.0f,168.0f, 136.0f,136.0f,144.0f,136.0f,128.0f,128.0f,128.0f,104.0f, 64.0f,40.0f,72.0f,128.0f,152.0f,136.0f,104.0f,88.0f, 96.0f,80.0f,32.0f,-33.0f,-89.0f,-113.0f,-121.0f,-121.0f, -113.0f,-97.0f,-81.0f,-65.0f,-57.0f,-65.0f,-81.0f,-81.0f, -89.0f,-97.0f,-97.0f,-97.0f,-105.0f,-121.0f,-121.0f,-113.0f, -89.0f,-81.0f,-73.0f,-73.0f,-57.0f,-57.0f,-65.0f,-73.0f, -57.0f,-33.0f,-9.0f,-1.0f,-1.0f,0.0f,8.0f,8.0f, 8.0f,8.0f,0.0f,-9.0f,-25.0f,-25.0f,-17.0f,-9.0f, -1.0f,0.0f,8.0f,24.0f,32.0f,40.0f,48.0f,56.0f, 72.0f,80.0f,96.0f,112.0f,136.0f,152.0f,176.0f,192.0f, 192.0f,192.0f,176.0f,160.0f,152.0f,152.0f,152.0f,160.0f, 152.0f,128.0f,128.0f,136.0f,152.0f,144.0f,120.0f,96.0f, 96.0f,96.0f,64.0f,8.0f,-25.0f,-41.0f,-41.0f,-33.0f, -41.0f,-49.0f,-65.0f,-65.0f,-49.0f,-49.0f,-49.0f,-57.0f, -57.0f,-49.0f,-33.0f,-41.0f,-49.0f,-65.0f,-73.0f,-73.0f, -89.0f,-105.0f,-121.0f,-105.0f,-81.0f,-57.0f,-49.0f,-57.0f, -65.0f,-49.0f,-33.0f,-25.0f,-25.0f,-33.0f,-17.0f,0.0f, 16.0f,16.0f,16.0f,32.0f,48.0f,64.0f,64.0f,56.0f, 56.0f,72.0f,88.0f,104.0f,104.0f,104.0f,104.0f,120.0f, 136.0f,128.0f,120.0f,112.0f,120.0f,128.0f,120.0f,96.0f, 72.0f,64.0f,64.0f,64.0f,64.0f,48.0f,48.0f,40.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f,48.0f, 0 }; t_CKUINT mand4_size = 1024; // data for mand5.raw... SAMPLE mand5_data[] = { 0.0f,273.0f,-1880.0f,-2683.0f,-2811.0f,-4016.0f,-3205.0f,1084.0f, -1125.0f,-5052.0f,-506.0f,3662.0f,8954.0f,8368.0f,-627.0f,-3615.0f, 6143.0f,7123.0f,3076.0f,-1518.0f,-4233.0f,3670.0f,6746.0f,7549.0f, 2626.0f,2794.0f,4867.0f,2168.0f,3485.0f,1975.0f,-370.0f,-3141.0f, -2249.0f,1172.0f,1397.0f,-635.0f,-2731.0f,-2330.0f,-5237.0f,-7526.0f, -7293.0f,-7325.0f,-4530.0f,-4948.0f,-6402.0f,-5373.0f,-5141.0f,-8417.0f, -10385.0f,-7060.0f,-3237.0f,-988.0f,-2370.0f,-3687.0f,-2217.0f,32.0f, 827.0f,-1277.0f,-1045.0f,714.0f,1807.0f,3156.0f,4481.0f,6127.0f, 6939.0f,6296.0f,4320.0f,5381.0f,7083.0f,7236.0f,7493.0f,7268.0f, 8183.0f,7019.0f,4232.0f,4176.0f,6328.0f,5324.0f,2144.0f,64.0f, 1244.0f,5758.0f,6666.0f,3991.0f,714.0f,-33.0f,522.0f,-1061.0f, -2498.0f,-3639.0f,-4297.0f,-4972.0f,-5622.0f,-4651.0f,-3133.0f,-2338.0f, -3799.0f,-5855.0f,-6434.0f,-6594.0f,-6771.0f,-6185.0f,-4225.0f,-3309.0f, -4257.0f,-6249.0f,-6755.0f,-3823.0f,-1623.0f,-1679.0f,-1470.0f,-531.0f, 200.0f,-378.0f,-844.0f,650.0f,1807.0f,1060.0f,811.0f,2578.0f, 5148.0f,5662.0f,3413.0f,1614.0f,1871.0f,3316.0f,3196.0f,1935.0f, 1116.0f,1268.0f,3164.0f,4312.0f,4369.0f,3437.0f,2979.0f,3445.0f, 2987.0f,1301.0f,-1061.0f,-2338.0f,-1358.0f,-1.0f,-330.0f,-916.0f, -747.0f,-595.0f,-1510.0f,-2948.0f,-3293.0f,-1888.0f,-1077.0f,-1840.0f, -2876.0f,-2860.0f,-1647.0f,-763.0f,-804.0f,-1165.0f,-996.0f,-442.0f, -161.0f,48.0f,361.0f,305.0f,690.0f,1156.0f,1678.0f,1935.0f, 1293.0f,1405.0f,2232.0f,2746.0f,3067.0f,2867.0f,2152.0f,1598.0f, 1341.0f,1477.0f,1437.0f,1196.0f,1180.0f,1188.0f,1405.0f,1582.0f, 1028.0f,-169.0f,-940.0f,-772.0f,160.0f,730.0f,481.0f,-209.0f, -1277.0f,-2370.0f,-3430.0f,-3237.0f,-2000.0f,-1294.0f,-1695.0f,-2306.0f, -2402.0f,-2185.0f,-2265.0f,-2956.0f,-3848.0f,-4378.0f,-4193.0f,-3550.0f, -2988.0f,-2635.0f,-2097.0f,-1454.0f,-1261.0f,-1221.0f,-1045.0f,-1181.0f, -1004.0f,-97.0f,1333.0f,2305.0f,2288.0f,1750.0f,1325.0f,1871.0f, 2666.0f,2762.0f,2634.0f,3276.0f,4634.0f,5790.0f,5517.0f,4096.0f, 3027.0f,2810.0f,2955.0f,2786.0f,2329.0f,2064.0f,1871.0f,1325.0f, 714.0f,232.0f,192.0f,722.0f,1052.0f,610.0f,-177.0f,-675.0f, -996.0f,-1382.0f,-1727.0f,-2089.0f,-2322.0f,-2049.0f,-1382.0f,-1125.0f, -1430.0f,-1679.0f,-1856.0f,-1976.0f,-2049.0f,-2249.0f,-2402.0f,-2193.0f, -1559.0f,-964.0f,-884.0f,-1093.0f,-1133.0f,-780.0f,-346.0f,-258.0f, -354.0f,-426.0f,-241.0f,24.0f,120.0f,64.0f,8.0f,208.0f, 722.0f,1309.0f,1558.0f,1461.0f,1204.0f,915.0f,658.0f,369.0f, 88.0f,56.0f,224.0f,257.0f,152.0f,120.0f,257.0f,313.0f, 88.0f,-33.0f,88.0f,393.0f,522.0f,136.0f,-394.0f,-635.0f, -506.0f,-354.0f,-474.0f,-683.0f,-595.0f,-145.0f,240.0f,224.0f, 72.0f,16.0f,-73.0f,-258.0f,-322.0f,-33.0f,433.0f,690.0f, 546.0f,248.0f,96.0f,128.0f,289.0f,570.0f,859.0f,995.0f, 955.0f,1068.0f,1461.0f,1686.0f,1469.0f,1003.0f,803.0f,1019.0f, 1236.0f,1100.0f,722.0f,441.0f,345.0f,176.0f,-17.0f,-97.0f, -129.0f,-169.0f,-266.0f,-354.0f,-466.0f,-643.0f,-723.0f,-747.0f, -836.0f,-1069.0f,-1189.0f,-972.0f,-691.0f,-691.0f,-1020.0f,-1342.0f, -1358.0f,-1165.0f,-1053.0f,-1061.0f,-1020.0f,-924.0f,-908.0f,-1004.0f, -1101.0f,-1093.0f,-956.0f,-812.0f,-699.0f,-506.0f,-330.0f,-306.0f, -394.0f,-362.0f,-145.0f,136.0f,393.0f,562.0f,698.0f,819.0f, 827.0f,738.0f,746.0f,963.0f,1244.0f,1413.0f,1501.0f,1542.0f, 1493.0f,1389.0f,1285.0f,1180.0f,1019.0f,851.0f,746.0f,730.0f, 771.0f,762.0f,674.0f,546.0f,393.0f,192.0f,16.0f,-73.0f, -145.0f,-177.0f,-105.0f,16.0f,24.0f,-113.0f,-354.0f,-506.0f, -434.0f,-258.0f,-137.0f,-97.0f,-129.0f,-217.0f,-402.0f,-627.0f, -731.0f,-683.0f,-531.0f,-330.0f,-161.0f,-49.0f,56.0f,112.0f, 48.0f,-73.0f,-177.0f,-217.0f,-193.0f,-177.0f,-209.0f,-249.0f, -290.0f,-274.0f,-193.0f,-105.0f,-57.0f,-121.0f,-266.0f,-394.0f, -418.0f,-370.0f,-322.0f,-346.0f,-418.0f,-490.0f,-490.0f,-394.0f, -209.0f,-65.0f,-1.0f,-33.0f,-121.0f,-193.0f,-241.0f,-249.0f, -209.0f,-145.0f,-81.0f,0.0f,128.0f,232.0f,281.0f,289.0f, 281.0f,305.0f,401.0f,497.0f,546.0f,538.0f,505.0f,473.0f, 505.0f,602.0f,682.0f,722.0f,730.0f,730.0f,746.0f,787.0f, 835.0f,843.0f,819.0f,779.0f,690.0f,570.0f,465.0f,417.0f, 433.0f,425.0f,337.0f,208.0f,112.0f,40.0f,-49.0f,-161.0f, -225.0f,-241.0f,-290.0f,-378.0f,-482.0f,-563.0f,-595.0f,-603.0f, -595.0f,-579.0f,-595.0f,-651.0f,-683.0f,-675.0f,-651.0f,-675.0f, -731.0f,-780.0f,-780.0f,-755.0f,-731.0f,-707.0f,-651.0f,-539.0f, -418.0f,-322.0f,-233.0f,-169.0f,-137.0f,-113.0f,-65.0f,16.0f, 152.0f,265.0f,289.0f,257.0f,240.0f,265.0f,329.0f,417.0f, 465.0f,473.0f,449.0f,441.0f,449.0f,457.0f,449.0f,433.0f, 441.0f,489.0f,514.0f,505.0f,481.0f,473.0f,457.0f,401.0f, 321.0f,257.0f,224.0f,216.0f,224.0f,224.0f,224.0f,200.0f, 144.0f,96.0f,56.0f,8.0f,-41.0f,-81.0f,-73.0f,-33.0f, -9.0f,-49.0f,-121.0f,-161.0f,-153.0f,-121.0f,-105.0f,-97.0f, -81.0f,-73.0f,-73.0f,-65.0f,-25.0f,24.0f,72.0f,88.0f, 72.0f,56.0f,40.0f,24.0f,-1.0f,-25.0f,-49.0f,-73.0f, -97.0f,-113.0f,-113.0f,-105.0f,-113.0f,-137.0f,-169.0f,-217.0f, -274.0f,-338.0f,-402.0f,-418.0f,-402.0f,-362.0f,-322.0f,-290.0f, -274.0f,-258.0f,-241.0f,-225.0f,-225.0f,-209.0f,-185.0f,-153.0f, -137.0f,-145.0f,-145.0f,-113.0f,-41.0f,40.0f,128.0f,184.0f, 232.0f,281.0f,329.0f,369.0f,385.0f,385.0f,385.0f,393.0f, 401.0f,417.0f,441.0f,473.0f,505.0f,514.0f,497.0f,457.0f, 425.0f,425.0f,441.0f,441.0f,409.0f,361.0f,337.0f,329.0f, 297.0f,224.0f,144.0f,96.0f,80.0f,88.0f,72.0f,24.0f, -33.0f,-81.0f,-121.0f,-161.0f,-201.0f,-241.0f,-249.0f,-266.0f, -282.0f,-306.0f,-314.0f,-314.0f,-306.0f,-314.0f,-338.0f,-370.0f, -378.0f,-362.0f,-338.0f,-330.0f,-338.0f,-354.0f,-338.0f,-306.0f, -266.0f,-217.0f,-185.0f,-161.0f,-129.0f,-97.0f,-89.0f,-89.0f, -65.0f,-25.0f,24.0f,64.0f,96.0f,144.0f,184.0f,208.0f, 208.0f,200.0f,192.0f,200.0f,208.0f,216.0f,224.0f,224.0f, 232.0f,248.0f,257.0f,273.0f,281.0f,273.0f,265.0f,248.0f, 232.0f,208.0f,176.0f,152.0f,128.0f,112.0f,96.0f,112.0f, 128.0f,160.0f,160.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f,176.0f, 0 }; t_CKUINT mand5_size = 1024; // data for mand6.raw... SAMPLE mand6_data[] = { 0.0f,136.0f,-1928.0f,-4667.0f,-6402.0f,-7630.0f,-7357.0f,-5325.0f, 2305.0f,8657.0f,8344.0f,3180.0f,-804.0f,2835.0f,4377.0f,489.0f, -3631.0f,-3068.0f,6384.0f,14247.0f,13516.0f,9404.0f,2377.0f,-1896.0f, -3221.0f,-1647.0f,3525.0f,6168.0f,4931.0f,1566.0f,530.0f,1052.0f, -362.0f,-4056.0f,-4105.0f,-1181.0f,369.0f,-2137.0f,-5815.0f,-7140.0f, -5671.0f,-3984.0f,-6538.0f,-8682.0f,-8658.0f,-5775.0f,-3020.0f,-2297.0f, -2249.0f,-3952.0f,-6377.0f,-7197.0f,-6169.0f,-3647.0f,-900.0f,-1727.0f, -3695.0f,-3117.0f,1598.0f,4730.0f,3999.0f,3581.0f,2594.0f,2642.0f, 3830.0f,6224.0f,7549.0f,6738.0f,6441.0f,6376.0f,5943.0f,4746.0f, 4698.0f,6240.0f,6995.0f,5991.0f,4818.0f,4577.0f,5605.0f,5750.0f, 3236.0f,562.0f,-651.0f,-354.0f,104.0f,-780.0f,-2378.0f,-4129.0f, -4378.0f,-2506.0f,-836.0f,160.0f,771.0f,-314.0f,-3229.0f,-6008.0f, -6522.0f,-4779.0f,-3775.0f,-4249.0f,-4522.0f,-3759.0f,-2201.0f,-1719.0f, -3526.0f,-5333.0f,-5116.0f,-3912.0f,-2587.0f,-2571.0f,-3687.0f,-3695.0f, -2699.0f,-1816.0f,-1783.0f,-1053.0f,1678.0f,3879.0f,4112.0f,3051.0f, 2674.0f,2971.0f,2465.0f,1429.0f,257.0f,554.0f,2810.0f,5397.0f, 7011.0f,7340.0f,6312.0f,4690.0f,3726.0f,3268.0f,2200.0f,570.0f, -137.0f,152.0f,530.0f,32.0f,-1583.0f,-3044.0f,-3607.0f,-2884.0f, -1976.0f,-1767.0f,-1663.0f,-2048.0f,-2089.0f,-1864.0f,-2233.0f,-2972.0f, -3414.0f,-2522.0f,-1711.0f,-1277.0f,-723.0f,64.0f,811.0f,602.0f, -490.0f,-1647.0f,-1390.0f,-346.0f,562.0f,698.0f,562.0f,1084.0f, 1774.0f,2425.0f,2650.0f,2650.0f,2481.0f,2369.0f,2361.0f,2031.0f, 1509.0f,1036.0f,1092.0f,1485.0f,1799.0f,2144.0f,2786.0f,2931.0f, 2377.0f,1702.0f,1421.0f,1445.0f,867.0f,-57.0f,-900.0f,-1623.0f, -2193.0f,-2587.0f,-2828.0f,-2876.0f,-2771.0f,-2442.0f,-2153.0f,-2306.0f, -2563.0f,-2932.0f,-3293.0f,-3390.0f,-3334.0f,-3165.0f,-2964.0f,-2972.0f, -3004.0f,-2659.0f,-2129.0f,-1534.0f,-1229.0f,-1020.0f,-715.0f,-233.0f, 192.0f,184.0f,337.0f,859.0f,1397.0f,1630.0f,1678.0f,1903.0f, 2313.0f,2682.0f,2995.0f,3228.0f,3421.0f,3758.0f,4031.0f,3830.0f, 3220.0f,2770.0f,3019.0f,3421.0f,3228.0f,2674.0f,2208.0f,1975.0f, 1598.0f,875.0f,72.0f,-386.0f,-659.0f,-1125.0f,-1791.0f,-2129.0f, -1727.0f,-1197.0f,-1085.0f,-1221.0f,-1358.0f,-1494.0f,-1928.0f,-2587.0f, -3020.0f,-3052.0f,-2755.0f,-2201.0f,-1551.0f,-1037.0f,-820.0f,-812.0f, -868.0f,-587.0f,-137.0f,-9.0f,-233.0f,-434.0f,-225.0f,-137.0f, -378.0f,-531.0f,-402.0f,0.0f,409.0f,618.0f,642.0f,586.0f, 795.0f,1108.0f,1076.0f,714.0f,297.0f,184.0f,417.0f,730.0f, 971.0f,1132.0f,1196.0f,1196.0f,1028.0f,642.0f,313.0f,281.0f, 401.0f,377.0f,104.0f,-161.0f,-298.0f,-418.0f,-627.0f,-820.0f, -892.0f,-868.0f,-804.0f,-755.0f,-828.0f,-988.0f,-1197.0f,-1398.0f, -1382.0f,-1109.0f,-675.0f,-249.0f,8.0f,160.0f,273.0f,297.0f, 385.0f,417.0f,417.0f,497.0f,562.0f,642.0f,795.0f,955.0f, 1068.0f,1108.0f,1108.0f,1260.0f,1566.0f,1734.0f,1614.0f,1405.0f, 1276.0f,1180.0f,947.0f,618.0f,369.0f,305.0f,417.0f,505.0f, 457.0f,257.0f,16.0f,-137.0f,-306.0f,-466.0f,-619.0f,-796.0f, -1037.0f,-1245.0f,-1446.0f,-1727.0f,-1872.0f,-1832.0f,-1695.0f,-1518.0f, -1350.0f,-1197.0f,-1101.0f,-1125.0f,-1269.0f,-1406.0f,-1398.0f,-1181.0f, -932.0f,-731.0f,-547.0f,-370.0f,-177.0f,-57.0f,0.0f,104.0f, 232.0f,401.0f,554.0f,618.0f,546.0f,385.0f,297.0f,361.0f, 481.0f,594.0f,698.0f,915.0f,1212.0f,1389.0f,1357.0f,1172.0f, 1003.0f,963.0f,987.0f,963.0f,907.0f,955.0f,1076.0f,1092.0f, 955.0f,730.0f,489.0f,321.0f,257.0f,176.0f,32.0f,-161.0f, -330.0f,-442.0f,-579.0f,-747.0f,-900.0f,-908.0f,-812.0f,-780.0f, -796.0f,-763.0f,-699.0f,-659.0f,-683.0f,-731.0f,-715.0f,-603.0f, -434.0f,-225.0f,0.0f,168.0f,216.0f,176.0f,120.0f,88.0f, 72.0f,72.0f,136.0f,224.0f,265.0f,208.0f,136.0f,152.0f, 200.0f,208.0f,128.0f,8.0f,-33.0f,-25.0f,-89.0f,-233.0f, -378.0f,-402.0f,-322.0f,-249.0f,-258.0f,-314.0f,-370.0f,-402.0f, -426.0f,-490.0f,-563.0f,-547.0f,-442.0f,-370.0f,-378.0f,-394.0f, -330.0f,-201.0f,-113.0f,-97.0f,-113.0f,-97.0f,-57.0f,-17.0f, 16.0f,88.0f,160.0f,208.0f,208.0f,208.0f,273.0f,385.0f, 505.0f,586.0f,610.0f,610.0f,578.0f,530.0f,497.0f,481.0f, 522.0f,562.0f,586.0f,602.0f,578.0f,554.0f,530.0f,505.0f, 497.0f,481.0f,449.0f,401.0f,321.0f,232.0f,128.0f,32.0f, -33.0f,-65.0f,-65.0f,-73.0f,-185.0f,-394.0f,-603.0f,-731.0f, -804.0f,-868.0f,-932.0f,-948.0f,-932.0f,-900.0f,-876.0f,-836.0f, -780.0f,-731.0f,-723.0f,-739.0f,-739.0f,-691.0f,-619.0f,-539.0f, -466.0f,-394.0f,-314.0f,-249.0f,-193.0f,-129.0f,-17.0f,104.0f, 232.0f,321.0f,337.0f,313.0f,289.0f,281.0f,289.0f,305.0f, 345.0f,417.0f,481.0f,522.0f,514.0f,473.0f,441.0f,425.0f, 417.0f,385.0f,345.0f,281.0f,208.0f,128.0f,88.0f,80.0f, 104.0f,128.0f,144.0f,152.0f,136.0f,88.0f,48.0f,16.0f, -1.0f,-49.0f,-113.0f,-161.0f,-169.0f,-145.0f,-129.0f,-129.0f, -113.0f,-105.0f,-105.0f,-121.0f,-137.0f,-145.0f,-129.0f,-113.0f, -105.0f,-97.0f,-105.0f,-105.0f,-97.0f,-89.0f,-73.0f,-65.0f, -49.0f,-41.0f,-25.0f,-17.0f,-1.0f,8.0f,32.0f,56.0f, 72.0f,72.0f,40.0f,8.0f,-25.0f,-57.0f,-81.0f,-105.0f, -145.0f,-193.0f,-258.0f,-330.0f,-386.0f,-426.0f,-434.0f,-418.0f, -394.0f,-378.0f,-378.0f,-378.0f,-370.0f,-378.0f,-378.0f,-362.0f, -314.0f,-249.0f,-177.0f,-105.0f,-33.0f,16.0f,56.0f,96.0f, 136.0f,176.0f,208.0f,257.0f,289.0f,313.0f,337.0f,361.0f, 385.0f,385.0f,385.0f,393.0f,385.0f,385.0f,385.0f,385.0f, 369.0f,337.0f,313.0f,281.0f,265.0f,232.0f,208.0f,176.0f, 144.0f,112.0f,96.0f,80.0f,48.0f,16.0f,0.0f,-1.0f, -17.0f,-49.0f,-89.0f,-129.0f,-177.0f,-233.0f,-290.0f,-338.0f, -370.0f,-386.0f,-394.0f,-402.0f,-418.0f,-426.0f,-426.0f,-410.0f, -394.0f,-370.0f,-346.0f,-322.0f,-306.0f,-282.0f,-266.0f,-249.0f, -233.0f,-209.0f,-185.0f,-161.0f,-121.0f,-73.0f,-25.0f,8.0f, 48.0f,80.0f,104.0f,128.0f,136.0f,136.0f,144.0f,160.0f, 168.0f,184.0f,192.0f,208.0f,208.0f,200.0f,184.0f,176.0f, 176.0f,168.0f,152.0f,136.0f,112.0f,80.0f,56.0f,48.0f, 48.0f,48.0f,48.0f,32.0f,16.0f,8.0f,0.0f,-1.0f, -25.0f,-33.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, -57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f,-57.0f, 0 }; t_CKUINT mand6_size = 1024; // data for mand7.raw... SAMPLE mand7_data[] = { 0.0f,-17.0f,-338.0f,-739.0f,-804.0f,-635.0f,-330.0f,-9.0f, 112.0f,168.0f,530.0f,1156.0f,1485.0f,1309.0f,883.0f,562.0f, 803.0f,1188.0f,1019.0f,618.0f,433.0f,586.0f,851.0f,803.0f, 96.0f,-555.0f,-474.0f,-137.0f,168.0f,-113.0f,-643.0f,-635.0f, -595.0f,-924.0f,-1374.0f,-1406.0f,-1302.0f,-1318.0f,-1398.0f,-1502.0f, -996.0f,-466.0f,-772.0f,-1494.0f,-1832.0f,-1575.0f,-900.0f,-258.0f, -105.0f,-474.0f,-715.0f,-490.0f,-547.0f,-490.0f,-161.0f,449.0f, 1100.0f,1413.0f,1333.0f,939.0f,843.0f,1164.0f,1558.0f,1445.0f, 1405.0f,1967.0f,2377.0f,2144.0f,2088.0f,1726.0f,995.0f,779.0f, 730.0f,746.0f,730.0f,746.0f,714.0f,369.0f,-97.0f,-241.0f, -338.0f,-330.0f,-274.0f,-466.0f,-571.0f,-780.0f,-972.0f,-1237.0f, -1286.0f,-1109.0f,-1181.0f,-1310.0f,-1253.0f,-940.0f,-643.0f,-627.0f, -932.0f,-996.0f,-812.0f,-755.0f,-948.0f,-1045.0f,-699.0f,-314.0f, -386.0f,-667.0f,-579.0f,-346.0f,72.0f,586.0f,979.0f,1236.0f, 1036.0f,650.0f,522.0f,578.0f,385.0f,192.0f,353.0f,795.0f, 1276.0f,1252.0f,875.0f,393.0f,-9.0f,-225.0f,-290.0f,-153.0f, -193.0f,-410.0f,-402.0f,-482.0f,-563.0f,-466.0f,-563.0f,-691.0f, -707.0f,-282.0f,88.0f,-41.0f,-225.0f,-386.0f,-370.0f,-290.0f, -233.0f,-105.0f,96.0f,160.0f,192.0f,441.0f,586.0f,514.0f, 232.0f,-33.0f,88.0f,570.0f,851.0f,835.0f,706.0f,586.0f, 650.0f,779.0f,1052.0f,1220.0f,1148.0f,883.0f,602.0f,546.0f, 554.0f,538.0f,393.0f,297.0f,281.0f,305.0f,345.0f,144.0f, -177.0f,-450.0f,-659.0f,-804.0f,-1004.0f,-1221.0f,-1286.0f,-1318.0f, -1286.0f,-1318.0f,-1398.0f,-1277.0f,-1101.0f,-916.0f,-892.0f,-876.0f, -747.0f,-675.0f,-531.0f,-506.0f,-523.0f,-482.0f,-410.0f,-282.0f, -225.0f,-105.0f,56.0f,257.0f,345.0f,273.0f,224.0f,200.0f, 337.0f,425.0f,417.0f,385.0f,449.0f,626.0f,795.0f,730.0f, 465.0f,361.0f,481.0f,706.0f,674.0f,522.0f,457.0f,522.0f, 706.0f,714.0f,586.0f,505.0f,514.0f,481.0f,393.0f,345.0f, 321.0f,265.0f,152.0f,32.0f,-105.0f,-290.0f,-426.0f,-410.0f, -233.0f,-73.0f,-65.0f,-169.0f,-233.0f,-274.0f,-346.0f,-402.0f, -450.0f,-402.0f,-274.0f,-193.0f,-81.0f,56.0f,88.0f,0.0f, -81.0f,-41.0f,24.0f,-57.0f,-137.0f,-193.0f,-193.0f,-177.0f, -153.0f,-169.0f,-217.0f,-153.0f,-81.0f,-73.0f,-97.0f,-65.0f, -1.0f,-17.0f,-105.0f,-193.0f,-241.0f,-258.0f,-241.0f,-217.0f, -161.0f,-73.0f,-49.0f,-89.0f,-169.0f,-290.0f,-378.0f,-378.0f, -314.0f,-249.0f,-266.0f,-346.0f,-378.0f,-306.0f,-177.0f,-65.0f, 0.0f,40.0f,80.0f,144.0f,232.0f,297.0f,297.0f,257.0f, 248.0f,313.0f,393.0f,433.0f,401.0f,353.0f,329.0f,361.0f, 441.0f,497.0f,522.0f,514.0f,497.0f,497.0f,497.0f,481.0f, 449.0f,401.0f,361.0f,313.0f,289.0f,305.0f,329.0f,289.0f, 144.0f,8.0f,-65.0f,-81.0f,-81.0f,-89.0f,-121.0f,-153.0f, -185.0f,-249.0f,-290.0f,-354.0f,-442.0f,-506.0f,-531.0f,-506.0f, -515.0f,-555.0f,-595.0f,-619.0f,-627.0f,-619.0f,-563.0f,-474.0f, -394.0f,-330.0f,-290.0f,-290.0f,-306.0f,-338.0f,-354.0f,-306.0f, -225.0f,-121.0f,-33.0f,24.0f,72.0f,88.0f,96.0f,112.0f, 128.0f,168.0f,216.0f,265.0f,265.0f,240.0f,216.0f,200.0f, 232.0f,273.0f,297.0f,329.0f,361.0f,401.0f,417.0f,377.0f, 313.0f,273.0f,273.0f,281.0f,265.0f,232.0f,192.0f,152.0f, 136.0f,128.0f,104.0f,64.0f,8.0f,-9.0f,-9.0f,0.0f, -1.0f,-17.0f,-49.0f,-73.0f,-97.0f,-113.0f,-121.0f,-121.0f, -129.0f,-129.0f,-129.0f,-129.0f,-129.0f,-129.0f,-105.0f,-49.0f, -1.0f,16.0f,32.0f,56.0f,40.0f,0.0f,-17.0f,-33.0f, -33.0f,-17.0f,0.0f,24.0f,32.0f,-1.0f,-57.0f,-81.0f, -65.0f,-41.0f,-57.0f,-89.0f,-121.0f,-129.0f,-137.0f,-161.0f, -177.0f,-185.0f,-193.0f,-177.0f,-161.0f,-153.0f,-161.0f,-193.0f, -233.0f,-258.0f,-258.0f,-241.0f,-225.0f,-209.0f,-193.0f,-153.0f, -113.0f,-73.0f,-49.0f,-41.0f,-9.0f,24.0f,88.0f,128.0f, 136.0f,136.0f,152.0f,168.0f,192.0f,208.0f,248.0f,289.0f, 321.0f,345.0f,345.0f,329.0f,297.0f,273.0f,265.0f,281.0f, 289.0f,273.0f,240.0f,216.0f,192.0f,168.0f,136.0f,112.0f, 96.0f,104.0f,96.0f,72.0f,24.0f,0.0f,-1.0f,-9.0f, -17.0f,-41.0f,-57.0f,-65.0f,-81.0f,-105.0f,-145.0f,-201.0f, -249.0f,-298.0f,-330.0f,-330.0f,-322.0f,-322.0f,-322.0f,-314.0f, -298.0f,-266.0f,-249.0f,-241.0f,-225.0f,-193.0f,-153.0f,-129.0f, -113.0f,-113.0f,-105.0f,-97.0f,-81.0f,-41.0f,-9.0f,16.0f, 24.0f,24.0f,8.0f,0.0f,0.0f,8.0f,16.0f,40.0f, 64.0f,88.0f,112.0f,128.0f,136.0f,136.0f,144.0f,144.0f, 144.0f,152.0f,152.0f,152.0f,152.0f,144.0f,144.0f,136.0f, 128.0f,128.0f,120.0f,128.0f,120.0f,104.0f,80.0f,56.0f, 40.0f,24.0f,16.0f,16.0f,32.0f,40.0f,40.0f,32.0f, 24.0f,24.0f,16.0f,16.0f,16.0f,24.0f,24.0f,32.0f, 32.0f,24.0f,0.0f,-17.0f,-17.0f,-17.0f,-25.0f,-33.0f, -49.0f,-57.0f,-65.0f,-73.0f,-73.0f,-73.0f,-89.0f,-97.0f, -97.0f,-97.0f,-89.0f,-97.0f,-105.0f,-97.0f,-89.0f,-81.0f, -89.0f,-89.0f,-97.0f,-105.0f,-113.0f,-129.0f,-137.0f,-137.0f, -137.0f,-137.0f,-129.0f,-121.0f,-113.0f,-97.0f,-81.0f,-57.0f, -41.0f,-17.0f,-1.0f,16.0f,24.0f,32.0f,48.0f,64.0f, 80.0f,96.0f,104.0f,112.0f,120.0f,120.0f,120.0f,120.0f, 128.0f,128.0f,136.0f,152.0f,152.0f,152.0f,144.0f,136.0f, 144.0f,144.0f,128.0f,120.0f,120.0f,112.0f,104.0f,96.0f, 88.0f,80.0f,64.0f,40.0f,16.0f,8.0f,0.0f,-1.0f, -9.0f,-25.0f,-41.0f,-57.0f,-65.0f,-73.0f,-73.0f,-73.0f, -81.0f,-81.0f,-89.0f,-97.0f,-113.0f,-121.0f,-129.0f,-129.0f, -121.0f,-113.0f,-105.0f,-97.0f,-97.0f,-97.0f,-97.0f,-97.0f, -89.0f,-81.0f,-73.0f,-65.0f,-65.0f,-73.0f,-65.0f,-65.0f, -49.0f,-41.0f,-41.0f,-33.0f,-25.0f,-25.0f,-17.0f,-9.0f, 8.0f,32.0f,40.0f,48.0f,64.0f,80.0f,88.0f,88.0f, 88.0f,96.0f,88.0f,88.0f,80.0f,80.0f,72.0f,72.0f, 72.0f,72.0f,72.0f,64.0f,64.0f,56.0f,48.0f,40.0f, 32.0f,32.0f,32.0f,32.0f,32.0f,32.0f,40.0f,40.0f, 40.0f,32.0f,24.0f,16.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f,24.0f, 0 }; t_CKUINT mand7_size = 1024; // data for mand8.raw... SAMPLE mand8_data[] = { 0.0f,-33.0f,-249.0f,-426.0f,-571.0f,-683.0f,-458.0f,-33.0f, 232.0f,232.0f,152.0f,168.0f,297.0f,425.0f,546.0f,762.0f, 883.0f,891.0f,771.0f,409.0f,168.0f,425.0f,1019.0f,1437.0f, 1325.0f,987.0f,618.0f,265.0f,-65.0f,-426.0f,-788.0f,-948.0f, -860.0f,-812.0f,-715.0f,-619.0f,-747.0f,-1125.0f,-1454.0f,-1406.0f, -1221.0f,-1133.0f,-1181.0f,-1229.0f,-1133.0f,-876.0f,-739.0f,-820.0f, -804.0f,-667.0f,-426.0f,-9.0f,281.0f,208.0f,16.0f,-17.0f, 120.0f,321.0f,457.0f,505.0f,650.0f,955.0f,1196.0f,1180.0f, 1003.0f,931.0f,971.0f,947.0f,1019.0f,1092.0f,883.0f,377.0f, -9.0f,80.0f,425.0f,722.0f,883.0f,931.0f,1036.0f,1028.0f, 714.0f,265.0f,-73.0f,-266.0f,-258.0f,-161.0f,-41.0f,168.0f, 208.0f,40.0f,-185.0f,-354.0f,-466.0f,-515.0f,-523.0f,-506.0f, -571.0f,-780.0f,-908.0f,-924.0f,-844.0f,-868.0f,-988.0f,-948.0f, -707.0f,-482.0f,-386.0f,-474.0f,-780.0f,-1012.0f,-996.0f,-812.0f, -563.0f,-322.0f,-233.0f,-177.0f,-73.0f,56.0f,297.0f,530.0f, 690.0f,827.0f,995.0f,1156.0f,1252.0f,1196.0f,971.0f,771.0f, 771.0f,963.0f,1019.0f,835.0f,522.0f,313.0f,345.0f,305.0f, 40.0f,-266.0f,-474.0f,-587.0f,-675.0f,-755.0f,-828.0f,-820.0f, -772.0f,-755.0f,-699.0f,-691.0f,-675.0f,-587.0f,-547.0f,-595.0f, -643.0f,-474.0f,-185.0f,16.0f,64.0f,40.0f,128.0f,305.0f, 489.0f,562.0f,497.0f,441.0f,433.0f,441.0f,481.0f,505.0f, 554.0f,618.0f,634.0f,578.0f,570.0f,690.0f,867.0f,963.0f, 827.0f,578.0f,393.0f,313.0f,337.0f,281.0f,160.0f,168.0f, 224.0f,305.0f,305.0f,128.0f,-65.0f,-225.0f,-330.0f,-490.0f, -667.0f,-755.0f,-852.0f,-924.0f,-940.0f,-868.0f,-755.0f,-755.0f, -844.0f,-1020.0f,-1053.0f,-964.0f,-924.0f,-940.0f,-948.0f,-860.0f, -731.0f,-635.0f,-587.0f,-490.0f,-354.0f,-233.0f,-153.0f,-65.0f, 72.0f,248.0f,353.0f,401.0f,489.0f,586.0f,690.0f,690.0f, 634.0f,650.0f,754.0f,875.0f,907.0f,915.0f,931.0f,979.0f, 1036.0f,1019.0f,947.0f,899.0f,835.0f,779.0f,674.0f,514.0f, 369.0f,192.0f,56.0f,-49.0f,-137.0f,-201.0f,-266.0f,-338.0f, -474.0f,-635.0f,-691.0f,-659.0f,-643.0f,-627.0f,-627.0f,-587.0f, -498.0f,-442.0f,-458.0f,-442.0f,-346.0f,-282.0f,-201.0f,-113.0f, -33.0f,16.0f,40.0f,64.0f,120.0f,184.0f,192.0f,104.0f, 0.0f,80.0f,160.0f,136.0f,40.0f,-41.0f,-33.0f,-1.0f, 32.0f,16.0f,-25.0f,-33.0f,0.0f,56.0f,104.0f,48.0f, -57.0f,-137.0f,-153.0f,-137.0f,-97.0f,-41.0f,-97.0f,-209.0f, -290.0f,-274.0f,-201.0f,-121.0f,-129.0f,-233.0f,-282.0f,-233.0f, -193.0f,-209.0f,-249.0f,-241.0f,-193.0f,-121.0f,-41.0f,-17.0f, -9.0f,8.0f,48.0f,96.0f,192.0f,313.0f,369.0f,393.0f, 409.0f,417.0f,417.0f,433.0f,433.0f,449.0f,481.0f,505.0f, 514.0f,497.0f,489.0f,441.0f,385.0f,353.0f,313.0f,265.0f, 224.0f,168.0f,112.0f,72.0f,32.0f,-9.0f,-73.0f,-121.0f, -161.0f,-161.0f,-161.0f,-217.0f,-306.0f,-370.0f,-402.0f,-410.0f, -402.0f,-410.0f,-426.0f,-458.0f,-466.0f,-450.0f,-450.0f,-458.0f, -442.0f,-402.0f,-338.0f,-290.0f,-241.0f,-201.0f,-169.0f,-153.0f, -153.0f,-137.0f,-105.0f,-65.0f,-9.0f,8.0f,24.0f,56.0f, 96.0f,136.0f,136.0f,136.0f,136.0f,120.0f,120.0f,112.0f, 120.0f,120.0f,144.0f,152.0f,168.0f,200.0f,232.0f,257.0f, 273.0f,273.0f,265.0f,248.0f,257.0f,257.0f,232.0f,208.0f, 184.0f,184.0f,168.0f,136.0f,104.0f,72.0f,48.0f,24.0f, 0.0f,-9.0f,-33.0f,-57.0f,-81.0f,-97.0f,-105.0f,-97.0f, -97.0f,-105.0f,-105.0f,-89.0f,-73.0f,-65.0f,-57.0f,-41.0f, -17.0f,-1.0f,16.0f,48.0f,72.0f,80.0f,80.0f,72.0f, 72.0f,72.0f,56.0f,32.0f,0.0f,-17.0f,-41.0f,-65.0f, -89.0f,-113.0f,-137.0f,-161.0f,-161.0f,-169.0f,-169.0f,-177.0f, -185.0f,-193.0f,-201.0f,-193.0f,-193.0f,-193.0f,-193.0f,-177.0f, -161.0f,-145.0f,-137.0f,-121.0f,-113.0f,-97.0f,-81.0f,-57.0f, -49.0f,-41.0f,-17.0f,-1.0f,0.0f,16.0f,40.0f,64.0f, 88.0f,104.0f,120.0f,136.0f,152.0f,160.0f,160.0f,160.0f, 168.0f,176.0f,176.0f,176.0f,184.0f,192.0f,200.0f,200.0f, 208.0f,216.0f,224.0f,216.0f,192.0f,176.0f,160.0f,136.0f, 112.0f,88.0f,64.0f,48.0f,40.0f,24.0f,0.0f,-1.0f, -17.0f,-33.0f,-57.0f,-81.0f,-105.0f,-113.0f,-129.0f,-153.0f, -177.0f,-201.0f,-201.0f,-201.0f,-209.0f,-225.0f,-233.0f,-225.0f, -225.0f,-217.0f,-201.0f,-185.0f,-169.0f,-145.0f,-129.0f,-105.0f, -89.0f,-73.0f,-65.0f,-49.0f,-17.0f,0.0f,16.0f,24.0f, 32.0f,40.0f,40.0f,40.0f,40.0f,40.0f,32.0f,32.0f, 32.0f,40.0f,48.0f,48.0f,40.0f,40.0f,32.0f,40.0f, 40.0f,40.0f,32.0f,32.0f,40.0f,48.0f,48.0f,40.0f, 40.0f,40.0f,56.0f,64.0f,72.0f,72.0f,72.0f,72.0f, 72.0f,72.0f,64.0f,64.0f,56.0f,56.0f,48.0f,48.0f, 40.0f,32.0f,24.0f,16.0f,24.0f,24.0f,24.0f,16.0f, 16.0f,16.0f,16.0f,24.0f,16.0f,16.0f,16.0f,8.0f, 8.0f,8.0f,8.0f,0.0f,0.0f,-1.0f,-9.0f,-25.0f, -33.0f,-57.0f,-73.0f,-89.0f,-97.0f,-113.0f,-113.0f,-113.0f, -121.0f,-121.0f,-129.0f,-137.0f,-145.0f,-145.0f,-145.0f,-153.0f, -153.0f,-145.0f,-137.0f,-121.0f,-113.0f,-105.0f,-89.0f,-81.0f, -73.0f,-57.0f,-41.0f,-25.0f,-9.0f,0.0f,24.0f,48.0f, 64.0f,80.0f,96.0f,104.0f,112.0f,120.0f,120.0f,112.0f, 112.0f,112.0f,112.0f,112.0f,104.0f,112.0f,120.0f,128.0f, 120.0f,112.0f,104.0f,96.0f,80.0f,64.0f,56.0f,48.0f, 40.0f,32.0f,32.0f,32.0f,16.0f,8.0f,0.0f,-1.0f, -9.0f,-9.0f,-17.0f,-25.0f,-33.0f,-41.0f,-49.0f,-57.0f, -65.0f,-73.0f,-81.0f,-81.0f,-81.0f,-81.0f,-89.0f,-89.0f, -89.0f,-89.0f,-97.0f,-97.0f,-97.0f,-97.0f,-81.0f,-81.0f, -73.0f,-65.0f,-57.0f,-49.0f,-33.0f,-33.0f,-25.0f,-17.0f, -17.0f,-9.0f,-9.0f,-9.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,0.0f,0.0f,8.0f,8.0f,16.0f,16.0f,16.0f, 8.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,-1.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,8.0f,16.0f,24.0f, 32.0f,32.0f,40.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f,56.0f, 0 }; t_CKUINT mand8_size = 1024; // data for mand9.raw... SAMPLE mand9_data[] = { 0.0f,40.0f,-595.0f,-1559.0f,-1478.0f,-386.0f,-217.0f,-1856.0f, -3012.0f,-1591.0f,1293.0f,3035.0f,2995.0f,2545.0f,2305.0f,1204.0f, 40.0f,594.0f,2023.0f,2224.0f,1598.0f,1285.0f,1622.0f,2513.0f, 2457.0f,618.0f,-1141.0f,-1398.0f,-836.0f,-450.0f,-1181.0f,-1800.0f, -1269.0f,-820.0f,-1310.0f,-2097.0f,-2466.0f,-2587.0f,-2482.0f,-2073.0f, -1992.0f,-2860.0f,-3486.0f,-2948.0f,-1759.0f,-860.0f,-755.0f,-306.0f, 562.0f,722.0f,401.0f,32.0f,369.0f,1389.0f,1702.0f,1036.0f, 289.0f,289.0f,963.0f,1887.0f,1951.0f,1517.0f,1405.0f,1542.0f, 2064.0f,2843.0f,3059.0f,2521.0f,1999.0f,1550.0f,1437.0f,1188.0f, 803.0f,787.0f,642.0f,401.0f,313.0f,377.0f,377.0f,-121.0f, -547.0f,-772.0f,-1221.0f,-1342.0f,-1318.0f,-1269.0f,-1470.0f,-1920.0f, -2169.0f,-1856.0f,-852.0f,-298.0f,-547.0f,-884.0f,-788.0f,-474.0f, -539.0f,-836.0f,-1213.0f,-1253.0f,-619.0f,24.0f,273.0f,40.0f, -145.0f,-346.0f,-563.0f,-683.0f,-1093.0f,-1253.0f,-828.0f,-81.0f, 811.0f,1244.0f,851.0f,329.0f,200.0f,449.0f,730.0f,738.0f, 859.0f,1469.0f,1758.0f,1349.0f,875.0f,746.0f,995.0f,1220.0f, 1084.0f,811.0f,947.0f,1180.0f,971.0f,176.0f,-812.0f,-1647.0f, -2097.0f,-1896.0f,-1334.0f,-956.0f,-988.0f,-1173.0f,-948.0f,-458.0f, -282.0f,-434.0f,-547.0f,-354.0f,144.0f,586.0f,586.0f,449.0f, 305.0f,224.0f,184.0f,-9.0f,-121.0f,176.0f,698.0f,931.0f, 698.0f,353.0f,144.0f,88.0f,176.0f,345.0f,457.0f,530.0f, 634.0f,473.0f,297.0f,144.0f,-57.0f,-65.0f,120.0f,465.0f, 730.0f,754.0f,618.0f,481.0f,345.0f,144.0f,-89.0f,-193.0f, -161.0f,-97.0f,-225.0f,-707.0f,-1117.0f,-1334.0f,-1414.0f,-1277.0f, -1085.0f,-796.0f,-539.0f,-490.0f,-603.0f,-667.0f,-450.0f,-153.0f, -9.0f,-105.0f,-290.0f,-378.0f,-354.0f,-249.0f,-225.0f,-306.0f, -314.0f,-169.0f,56.0f,321.0f,465.0f,489.0f,457.0f,321.0f, 152.0f,40.0f,-49.0f,0.0f,208.0f,530.0f,819.0f,907.0f, 867.0f,835.0f,835.0f,827.0f,795.0f,795.0f,819.0f,843.0f, 730.0f,546.0f,393.0f,265.0f,112.0f,-17.0f,-81.0f,-129.0f, -225.0f,-410.0f,-659.0f,-852.0f,-988.0f,-1012.0f,-908.0f,-804.0f, -691.0f,-531.0f,-306.0f,-9.0f,160.0f,144.0f,96.0f,48.0f, 80.0f,160.0f,265.0f,353.0f,305.0f,184.0f,-33.0f,-241.0f, -306.0f,-274.0f,-209.0f,-249.0f,-274.0f,-177.0f,-41.0f,-9.0f, -73.0f,-209.0f,-338.0f,-282.0f,-153.0f,8.0f,120.0f,144.0f, 112.0f,88.0f,168.0f,248.0f,265.0f,176.0f,48.0f,16.0f, 72.0f,128.0f,208.0f,248.0f,176.0f,16.0f,-113.0f,-129.0f, -73.0f,-49.0f,-65.0f,-89.0f,-113.0f,-105.0f,-57.0f,24.0f, 120.0f,184.0f,200.0f,160.0f,112.0f,64.0f,-1.0f,-65.0f, -153.0f,-233.0f,-266.0f,-258.0f,-185.0f,-113.0f,-97.0f,-97.0f, -25.0f,64.0f,144.0f,160.0f,160.0f,120.0f,64.0f,32.0f, 0.0f,-1.0f,56.0f,168.0f,289.0f,353.0f,337.0f,305.0f, 297.0f,329.0f,369.0f,305.0f,176.0f,56.0f,16.0f,56.0f, 56.0f,16.0f,-65.0f,-161.0f,-225.0f,-266.0f,-290.0f,-282.0f, -266.0f,-274.0f,-282.0f,-298.0f,-290.0f,-233.0f,-169.0f,-121.0f, -113.0f,-121.0f,-137.0f,-137.0f,-113.0f,-97.0f,-145.0f,-161.0f, -129.0f,-73.0f,-17.0f,0.0f,0.0f,-41.0f,-89.0f,-137.0f, -153.0f,-145.0f,-121.0f,-97.0f,-97.0f,-49.0f,8.0f,96.0f, 176.0f,257.0f,329.0f,353.0f,329.0f,297.0f,297.0f,281.0f, 248.0f,200.0f,168.0f,152.0f,192.0f,265.0f,337.0f,385.0f, 353.0f,273.0f,176.0f,104.0f,72.0f,24.0f,-33.0f,-89.0f, -129.0f,-161.0f,-177.0f,-169.0f,-145.0f,-153.0f,-185.0f,-201.0f, -193.0f,-153.0f,-145.0f,-161.0f,-153.0f,-129.0f,-97.0f,-73.0f, -73.0f,-65.0f,-57.0f,-65.0f,-57.0f,-25.0f,0.0f,16.0f, 8.0f,8.0f,-1.0f,-41.0f,-81.0f,-81.0f,-41.0f,0.0f, 16.0f,8.0f,-17.0f,-25.0f,-9.0f,8.0f,16.0f,0.0f, -17.0f,-25.0f,-9.0f,0.0f,8.0f,-1.0f,-17.0f,-41.0f, -41.0f,-33.0f,-9.0f,8.0f,32.0f,32.0f,32.0f,48.0f, 56.0f,64.0f,48.0f,40.0f,48.0f,64.0f,80.0f,96.0f, 80.0f,40.0f,-1.0f,-41.0f,-49.0f,-33.0f,-1.0f,8.0f, 24.0f,48.0f,80.0f,104.0f,96.0f,56.0f,16.0f,-1.0f, -9.0f,-17.0f,-25.0f,-17.0f,8.0f,32.0f,48.0f,48.0f, 48.0f,64.0f,96.0f,120.0f,128.0f,120.0f,112.0f,80.0f, 48.0f,16.0f,0.0f,-1.0f,-9.0f,-25.0f,-33.0f,-41.0f, -73.0f,-121.0f,-169.0f,-209.0f,-225.0f,-225.0f,-209.0f,-185.0f, -153.0f,-129.0f,-121.0f,-105.0f,-81.0f,-57.0f,-49.0f,-33.0f, -25.0f,-1.0f,8.0f,16.0f,8.0f,8.0f,-1.0f,-9.0f, -9.0f,-1.0f,16.0f,40.0f,56.0f,64.0f,72.0f,88.0f, 104.0f,120.0f,120.0f,104.0f,96.0f,96.0f,96.0f,88.0f, 64.0f,40.0f,40.0f,40.0f,48.0f,72.0f,96.0f,112.0f, 104.0f,88.0f,80.0f,72.0f,72.0f,56.0f,32.0f,16.0f, 16.0f,16.0f,8.0f,-1.0f,-1.0f,-9.0f,-17.0f,-33.0f, -49.0f,-49.0f,-33.0f,-33.0f,-33.0f,-25.0f,-25.0f,-25.0f, -33.0f,-33.0f,-33.0f,-41.0f,-41.0f,-25.0f,-9.0f,0.0f, -1.0f,-33.0f,-57.0f,-73.0f,-73.0f,-65.0f,-49.0f,-41.0f, -25.0f,-1.0f,8.0f,16.0f,24.0f,40.0f,40.0f,32.0f, 24.0f,16.0f,8.0f,8.0f,-1.0f,-17.0f,-33.0f,-41.0f, -41.0f,-33.0f,-17.0f,-9.0f,0.0f,8.0f,8.0f,8.0f, 16.0f,32.0f,48.0f,56.0f,64.0f,88.0f,112.0f,120.0f, 112.0f,96.0f,72.0f,56.0f,48.0f,40.0f,40.0f,40.0f, 48.0f,48.0f,40.0f,24.0f,16.0f,16.0f,8.0f,0.0f, -9.0f,-25.0f,-33.0f,-25.0f,-25.0f,-25.0f,-25.0f,-25.0f, -17.0f,-1.0f,0.0f,8.0f,8.0f,8.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,8.0f,16.0f,16.0f,16.0f, 8.0f,-1.0f,-17.0f,-33.0f,-41.0f,-41.0f,-33.0f,-25.0f, -17.0f,-9.0f,-1.0f,0.0f,8.0f,16.0f,16.0f,16.0f, 16.0f,8.0f,8.0f,8.0f,0.0f,0.0f,-1.0f,-9.0f, -17.0f,-9.0f,-1.0f,8.0f,8.0f,16.0f,16.0f,24.0f, 24.0f,32.0f,32.0f,32.0f,32.0f,32.0f,40.0f,40.0f, 32.0f,24.0f,16.0f,16.0f,8.0f,16.0f,16.0f,8.0f, 8.0f,8.0f,0.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, -1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f,-1.0f, 0 }; t_CKUINT mand9_size = 1024; // data for mandpluk.raw... SAMPLE mandpluk_data[] = { 0.0f,8.0f,96.0f,224.0f,265.0f,16.0f,-498.0f,-948.0f, -651.0f,754.0f,2754.0f,3847.0f,2160.0f,-3165.0f,-11044.0f,-18722.0f, -23018.0f,-22119.0f,-16425.0f,-8144.0f,361.0f,7766.0f,14006.0f,19628.0f, 24664.0f,28358.0f,29788.0f,28712.0f,25869.0f,22335.0f,18648.0f,14336.0f, 8465.0f,570.0f,-8506.0f,-16939.0f,-22745.0f,-24817.0f,-23275.0f,-19284.0f, -14497.0f,-10658.0f,-9204.0f,-11003.0f,-15686.0f,-21500.0f,-25709.0f,-25741.0f, -20673.0f,-11983.0f,-3125.0f,1935.0f,787.0f,-6144.0f,-15605.0f,-23018.0f, -24785.0f,-20095.0f,-11277.0f,-2635.0f,2184.0f,2128.0f,-804.0f,-2948.0f, -1229.0f,5172.0f,14456.0f,23523.0f,29683.0f,31964.0f,31153.0f,29057.0f, 27362.0f,26937.0f,27555.0f,28190.0f,27652.0f,25090.0f,20568.0f,15187.0f, 10617.0f,8440.0f,9131.0f,11790.0f,14488.0f,15364.0f,13613.0f,9854.0f, 5686.0f,2698.0f,1542.0f,1662.0f,1879.0f,931.0f,-1783.0f,-6241.0f, -11766.0f,-17380.0f,-22215.0f,-25669.0f,-27620.0f,-28407.0f,-28648.0f,-28833.0f, -29114.0f,-29178.0f,-28640.0f,-27251.0f,-25307.0f,-23364.0f,-21926.0f,-21059.0f, -20344.0f,-19212.0f,-17533.0f,-15710.0f,-14385.0f,-13734.0f,-13076.0f,-11285.0f, -7510.0f,-2089.0f,3357.0f,6866.0f,7388.0f,5437.0f,2947.0f,2048.0f, 4047.0f,8746.0f,14858.0f,20857.0f,25628.0f,28728.0f,30326.0f,30824.0f, 30768.0f,30591.0f,30454.0f,30214.0f,29386.0f,27547.0f,24616.0f,21122.0f, 17845.0f,15331.0f,13573.0f,12103.0f,10472.0f,8770.0f,7356.0f,6585.0f, 6240.0f,5437.0f,3324.0f,-137.0f,-4008.0f,-6795.0f,-7413.0f,-5960.0f, -3542.0f,-1735.0f,-1438.0f,-2554.0f,-4337.0f,-5928.0f,-6883.0f,-7317.0f, -7743.0f,-8867.0f,-11429.0f,-15758.0f,-21348.0f,-26504.0f,-28809.0f,-26303.0f, -18834.0f,-8570.0f,915.0f,6505.0f,7244.0f,4513.0f,738.0f,-2354.0f, -4755.0f,-7534.0f,-11357.0f,-15509.0f,-18111.0f,-17573.0f,-13975.0f,-9269.0f, -6096.0f,-6088.0f,-8707.0f,-11903.0f,-13525.0f,-12851.0f,-10859.0f,-9365.0f, -9518.0f,-10955.0f,-12240.0f,-11927.0f,-9702.0f,-6393.0f,-3390.0f,-1575.0f, -884.0f,-683.0f,-346.0f,240.0f,891.0f,1293.0f,1509.0f,2007.0f, 3204.0f,5260.0f,7798.0f,10007.0f,11107.0f,10737.0f,9316.0f,7951.0f, 7910.0f,9910.0f,13629.0f,17717.0f,20720.0f,21965.0f,21941.0f,21901.0f, 22801.0f,24455.0f,25595.0f,24760.0f,21491.0f,16793.0f,12601.0f,10617.0f, 11292.0f,13661.0f,16151.0f,17532.0f,17500.0f,16480.0f,14970.0f,13139.0f, 10770.0f,7846.0f,4634.0f,1807.0f,-217.0f,-1462.0f,-2330.0f,-3237.0f, -4145.0f,-4578.0f,-4185.0f,-3277.0f,-2860.0f,-4225.0f,-8040.0f,-13871.0f, -20280.0f,-25580.0f,-28817.0f,-30054.0f,-30054.0f,-29556.0f,-28841.0f,-27669.0f, -25773.0f,-23211.0f,-20280.0f,-17188.0f,-13871.0f,-10168.0f,-6289.0f,-3068.0f, -1583.0f,-2474.0f,-5406.0f,-9028.0f,-11831.0f,-12803.0f,-12080.0f,-10514.0f, -9060.0f,-8120.0f,-7486.0f,-6610.0f,-5092.0f,-2972.0f,-587.0f,1550.0f, 3148.0f,4168.0f,4802.0f,5300.0f,5919.0f,6698.0f,7589.0f,8392.0f, 8858.0f,8794.0f,8192.0f,7268.0f,6481.0f,6417.0f,7613.0f,10223.0f, 13797.0f,17283.0f,19427.0f,19347.0f,17187.0f,14239.0f,12312.0f,12785.0f, 15701.0f,19660.0f,22640.0f,23162.0f,21050.0f,17540.0f,14311.0f,12488.0f, 12111.0f,12231.0f,11790.0f,10248.0f,7902.0f,5493.0f,3766.0f,2995.0f, 3019.0f,3405.0f,3654.0f,3437.0f,2545.0f,1052.0f,-772.0f,-2522.0f, -3880.0f,-4675.0f,-5092.0f,-5494.0f,-6112.0f,-6980.0f,-8000.0f,-9156.0f, -10650.0f,-12875.0f,-16087.0f,-20151.0f,-24408.0f,-27869.0f,-29773.0f,-29837.0f, -28488.0f,-26544.0f,-24785.0f,-23589.0f,-22761.0f,-21846.0f,-20440.0f,-18521.0f, -16441.0f,-14658.0f,-13461.0f,-12738.0f,-12112.0f,-11044.0f,-9325.0f,-7084.0f, -4715.0f,-2635.0f,-1053.0f,176.0f,1429.0f,2923.0f,4706.0f,6465.0f, 7806.0f,8368.0f,8175.0f,7661.0f,7541.0f,8449.0f,10681.0f,14070.0f, 17982.0f,21756.0f,24881.0f,27138.0f,28503.0f,28985.0f,28615.0f,27403.0f, 25531.0f,23315.0f,21130.0f,19243.0f,17677.0f,16279.0f,14785.0f,13091.0f, 11203.0f,9252.0f,7372.0f,5694.0f,4232.0f,2971.0f,1839.0f,690.0f, -506.0f,-1896.0f,-3366.0f,-4651.0f,-5502.0f,-5711.0f,-5390.0f,-5028.0f, -5229.0f,-6337.0f,-8209.0f,-10104.0f,-11156.0f,-10795.0f,-9156.0f,-7028.0f, -5406.0f,-4908.0f,-5470.0f,-6482.0f,-7261.0f,-7534.0f,-7486.0f,-7446.0f, -7494.0f,-7317.0f,-6450.0f,-4811.0f,-2892.0f,-1526.0f,-1406.0f,-2506.0f, -4201.0f,-5775.0f,-6907.0f,-8016.0f,-9855.0f,-12803.0f,-16489.0f,-19830.0f, -21645.0f,-21404.0f,-19452.0f,-16754.0f,-14296.0f,-12521.0f,-11341.0f,-10329.0f, -9196.0f,-7911.0f,-6650.0f,-5614.0f,-4731.0f,-3920.0f,-3044.0f,-2145.0f, -1294.0f,-498.0f,329.0f,1381.0f,2706.0f,4168.0f,5565.0f,6778.0f, 7830.0f,8906.0f,10231.0f,11902.0f,13926.0f,16151.0f,18383.0f,20359.0f, 21748.0f,22295.0f,21981.0f,21090.0f,20150.0f,19620.0f,19628.0f,19877.0f, 19853.0f,19138.0f,17765.0f,16094.0f,14568.0f,13452.0f,12609.0f,11709.0f, 10505.0f,8946.0f,7252.0f,5718.0f,4433.0f,3381.0f,2401.0f,1397.0f, 313.0f,-731.0f,-1695.0f,-2546.0f,-3438.0f,-4530.0f,-5968.0f,-7743.0f, -9654.0f,-11236.0f,-12040.0f,-11871.0f,-10987.0f,-10176.0f,-10377.0f,-12152.0f, -15276.0f,-18770.0f,-21324.0f,-22031.0f,-20898.0f,-18890.0f,-17332.0f,-17083.0f, -18071.0f,-19348.0f,-19734.0f,-18593.0f,-16240.0f,-13549.0f,-11485.0f,-10417.0f, -10040.0f,-9662.0f,-8779.0f,-7325.0f,-5582.0f,-3944.0f,-2563.0f,-1438.0f, -458.0f,377.0f,971.0f,1317.0f,1622.0f,2208.0f,3357.0f,5075.0f, 7003.0f,8754.0f,10127.0f,11308.0f,12761.0f,14817.0f,17387.0f,19853.0f, 21347.0f,21299.0f,19765.0f,17428.0f,15299.0f,14167.0f,14191.0f,14946.0f, 15717.0f,15886.0f,15267.0f,14087.0f,12705.0f,11412.0f,10280.0f,9244.0f, 8208.0f,7099.0f,5911.0f,4658.0f,3397.0f,2248.0f,1397.0f,947.0f, 811.0f,722.0f,361.0f,-426.0f,-1551.0f,-2683.0f,-3550.0f,-4080.0f, -4514.0f,-5253.0f,-6538.0f,-8385.0f,-10409.0f,-12088.0f,-12955.0f,-12899.0f, -12184.0f,-11325.0f,-10827.0f,-10915.0f,-11381.0f,-11807.0f,-11911.0f,-11702.0f, -11542.0f,-11847.0f,-12738.0f,-13927.0f,-14818.0f,-14931.0f,-14168.0f,-12835.0f, -11477.0f,-10506.0f,-10008.0f,-9791.0f,-9598.0f,-9204.0f,-8522.0f,-7574.0f, -6377.0f,-5052.0f,-3783.0f,-2771.0f,-2129.0f,-1816.0f,-1575.0f,-1165.0f, -354.0f,859.0f,2329.0f,3822.0f,5115.0f,5999.0f,6376.0f,6352.0f, 6111.0f,5927.0f,5983.0f,6248.0f,6513.0f,6489.0f,6135.0f,5734.0f, 5838.0f,6898.0f,9091.0f,12071.0f,15171.0f,17789.0f,19540.0f,20399.0f, 20504.0f,20038.0f,19074.0f,17701.0f,16054.0f,14376.0f,12946.0f,11886.0f, 11147.0f,10521.0f,9806.0f,8914.0f,7910.0f,6890.0f,5943.0f,5051.0f, 4128.0f,3148.0f,2072.0f,995.0f,-73.0f,-1109.0f,-2065.0f,-2932.0f, -3663.0f,-4185.0f,-4522.0f,-4771.0f,-4988.0f,-5253.0f,-5606.0f,-6056.0f, -6626.0f,-7357.0f,-8257.0f,-9309.0f,-10377.0f,-11373.0f,-12321.0f,-13341.0f, -14626.0f,-16240.0f,-17927.0f,-19236.0f,-19726.0f,-19147.0f,-17702.0f,-15903.0f, -14312.0f,-13252.0f,-12714.0f,-12409.0f,-12056.0f,-11469.0f,-10746.0f,-10080.0f, -9558.0f,-9140.0f,-8658.0f,-7935.0f,-6899.0f,-5671.0f,-4378.0f,-3205.0f, -2145.0f,-1141.0f,-113.0f,971.0f,2104.0f,3180.0f,4136.0f,5027.0f, 5935.0f,7003.0f,8304.0f,9798.0f,11340.0f,12769.0f,14062.0f,15299.0f, 16592.0f,17966.0f,19259.0f,20150.0f,20399.0f,19965.0f,19042.0f,17958.0f, 16938.0f,16022.0f,15115.0f,14135.0f,13107.0f,12167.0f,11420.0f,10818.0f, 10231.0f,9420.0f,8344.0f,7115.0f,5870.0f,4730.0f,3710.0f,2690.0f, 1574.0f,337.0f,-932.0f,-2121.0f,-3197.0f,-4153.0f,-5020.0f,-5847.0f, -6659.0f,-7470.0f,-8305.0f,-9229.0f,-10240.0f,-11317.0f,-12417.0f,-13509.0f, -14585.0f,-15622.0f,-16561.0f,-17324.0f,-17782.0f,-17870.0f,-17573.0f,-16923.0f, -15999.0f,-14867.0f,-13590.0f,-12280.0f,-11044.0f,-9975.0f,-9108.0f,-8409.0f, -7815.0f,-7277.0f,-6787.0f,-6321.0f,-5855.0f,-5213.0f,-4297.0f,-3133.0f, -1783.0f,-394.0f,939.0f,2224.0f,3557.0f,4931.0f,6288.0f,7429.0f, 8191.0f,8449.0f,8256.0f,7782.0f,7268.0f,6995.0f,7180.0f,7934.0f, 9115.0f,10440.0f,11541.0f,12079.0f,11990.0f,11412.0f,10593.0f,9742.0f, 8874.0f,7886.0f,6674.0f,5316.0f,4055.0f,3252.0f,3148.0f,3766.0f, 4891.0f,6184.0f,7324.0f,8087.0f,8384.0f,8312.0f,7999.0f,7557.0f, 7083.0f,6561.0f,5935.0f,5124.0f,4144.0f,3124.0f,2240.0f,1670.0f, 1445.0f,1461.0f,1533.0f,1437.0f,1084.0f,497.0f,-225.0f,-980.0f, -1703.0f,-2370.0f,-3012.0f,-3687.0f,-4426.0f,-5301.0f,-6321.0f,-7373.0f, -8225.0f,-8690.0f,-8690.0f,-8409.0f,-8257.0f,-8618.0f,-9670.0f,-11212.0f, -12819.0f,-14120.0f,-14947.0f,-15501.0f,-16063.0f,-16722.0f,-17316.0f,-17445.0f, -16818.0f,-15461.0f,-13710.0f,-11967.0f,-10481.0f,-9245.0f,-8056.0f,-6795.0f, -5510.0f,-4345.0f,-3422.0f,-2667.0f,-1904.0f,-1012.0f,-57.0f,779.0f, 1309.0f,1574.0f,1799.0f,2305.0f,3284.0f,4650.0f,6216.0f,7782.0f, 9220.0f,10569.0f,11902.0f,13147.0f,14199.0f,14922.0f,15283.0f,15355.0f, 15275.0f,15171.0f,15115.0f,15131.0f,15211.0f,15331.0f,15388.0f,15243.0f, 14753.0f,13813.0f,12488.0f,10986.0f,9549.0f,8296.0f,7228.0f,6200.0f, 5075.0f,3847.0f,2634.0f,1662.0f,995.0f,626.0f,385.0f,48.0f, -498.0f,-1261.0f,-2105.0f,-2924.0f,-3623.0f,-4225.0f,-4851.0f,-5606.0f, -6546.0f,-7590.0f,-8562.0f,-9317.0f,-9718.0f,-9815.0f,-9775.0f,-9791.0f, -10008.0f,-10441.0f,-10971.0f,-11389.0f,-11558.0f,-11445.0f,-11140.0f,-10859.0f, -10795.0f,-11044.0f,-11517.0f,-11975.0f,-12112.0f,-11662.0f,-10618.0f,-9204.0f, -7783.0f,-6626.0f,-5847.0f,-5269.0f,-4611.0f,-3703.0f,-2554.0f,-1430.0f, -563.0f,-113.0f,-9.0f,-41.0f,56.0f,457.0f,1252.0f,2457.0f, 3967.0f,5597.0f,7123.0f,8376.0f,9308.0f,9999.0f,10601.0f,11179.0f, 11645.0f,11806.0f,11581.0f,11115.0f,10705.0f,10617.0f,10874.0f,11268.0f, 11492.0f,11380.0f,11002.0f,10569.0f,10207.0f,9838.0f,9252.0f,8296.0f, 7075.0f,5806.0f,4786.0f,4112.0f,3662.0f,3188.0f,2553.0f,1831.0f, 1172.0f,746.0f,505.0f,289.0f,-121.0f,-780.0f,-1559.0f,-2289.0f, -2924.0f,-3542.0f,-4289.0f,-5293.0f,-6361.0f,-7213.0f,-7534.0f,-7277.0f, -6731.0f,-6329.0f,-6377.0f,-6851.0f,-7421.0f,-7711.0f,-7646.0f,-7462.0f, -7558.0f,-8160.0f,-9124.0f,-10064.0f,-10618.0f,-10706.0f,-10498.0f,-10232.0f, -9959.0f,-9510.0f,-8682.0f,-7470.0f,-6120.0f,-4988.0f,-4281.0f,-3888.0f, -3486.0f,-2820.0f,-1960.0f,-1157.0f,-707.0f,-651.0f,-715.0f,-531.0f, 160.0f,1268.0f,2449.0f,3397.0f,3983.0f,4312.0f,4626.0f,5043.0f, 5485.0f,5774.0f,5782.0f,5549.0f,5228.0f,4995.0f,4875.0f,4778.0f, 4569.0f,4256.0f,4039.0f,4144.0f,4746.0f,5718.0f,6698.0f,7316.0f, 7396.0f,7035.0f,6537.0f,6184.0f,6071.0f,6055.0f,5935.0f,5629.0f, 5252.0f,4995.0f,4987.0f,5188.0f,5405.0f,5445.0f,5292.0f,5027.0f, 4794.0f,4601.0f,4361.0f,3943.0f,3244.0f,2353.0f,1437.0f,626.0f, -25.0f,-587.0f,-1133.0f,-1751.0f,-2410.0f,-3093.0f,-3711.0f,-4257.0f, -4747.0f,-5213.0f,-5671.0f,-6136.0f,-6594.0f,-7076.0f,-7622.0f,-8273.0f, -9036.0f,-9823.0f,-10441.0f,-10738.0f,-10626.0f,-10184.0f,-9606.0f,-9068.0f, -8618.0f,-8168.0f,-7558.0f,-6763.0f,-5936.0f,-5293.0f,-4988.0f,-4972.0f, -4988.0f,-4795.0f,-4265.0f,-3518.0f,-2731.0f,-2057.0f,-1486.0f,-876.0f, -137.0f,714.0f,1566.0f,2272.0f,2794.0f,3148.0f,3397.0f,3614.0f, 3798.0f,3983.0f,4216.0f,4601.0f,5188.0f,5943.0f,6746.0f,7493.0f, 8063.0f,8424.0f,8657.0f,8786.0f,8842.0f,8778.0f,8593.0f,8296.0f, 7951.0f,7589.0f,7220.0f,6794.0f,6304.0f,5798.0f,5364.0f,5083.0f, 4931.0f,4818.0f,4585.0f,4160.0f,3541.0f,2794.0f,2047.0f,1325.0f, 634.0f,-25.0f,-659.0f,-1245.0f,-1751.0f,-2137.0f,-2394.0f,-2482.0f, -2402.0f,-2177.0f,-1912.0f,-1767.0f,-1888.0f,-2322.0f,-3028.0f,-3839.0f, -4611.0f,-5293.0f,-5904.0f,-6498.0f,-7124.0f,-7678.0f,-8056.0f,-8152.0f, -7952.0f,-7542.0f,-7036.0f,-6530.0f,-6120.0f,-5823.0f,-5695.0f,-5799.0f, -6128.0f,-6578.0f,-6980.0f,-7116.0f,-6899.0f,-6345.0f,-5606.0f,-4851.0f, -4169.0f,-3558.0f,-2940.0f,-2257.0f,-1518.0f,-788.0f,-169.0f,273.0f, 546.0f,682.0f,754.0f,867.0f,1116.0f,1542.0f,2152.0f,2907.0f, 3726.0f,4513.0f,5252.0f,5895.0f,6457.0f,6939.0f,7332.0f,7597.0f, 7710.0f,7653.0f,7420.0f,7035.0f,6553.0f,6079.0f,5670.0f,5405.0f, 5284.0f,5260.0f,5260.0f,5252.0f,5212.0f,5148.0f,5035.0f,4826.0f, 4505.0f,4063.0f,3533.0f,2979.0f,2449.0f,1975.0f,1517.0f,1108.0f, 779.0f,602.0f,618.0f,762.0f,915.0f,915.0f,674.0f,192.0f, -402.0f,-1029.0f,-1623.0f,-2249.0f,-3004.0f,-3912.0f,-4868.0f,-5695.0f, -6201.0f,-6321.0f,-6145.0f,-5863.0f,-5647.0f,-5566.0f,-5590.0f,-5598.0f, -5550.0f,-5454.0f,-5414.0f,-5494.0f,-5727.0f,-6024.0f,-6273.0f,-6442.0f, -6466.0f,-6369.0f,-6161.0f,-5815.0f,-5333.0f,-4739.0f,-4113.0f,-3558.0f, -3093.0f,-2723.0f,-2418.0f,-2105.0f,-1767.0f,-1398.0f,-972.0f,-482.0f, 80.0f,706.0f,1333.0f,1903.0f,2369.0f,2786.0f,3212.0f,3694.0f, 4184.0f,4634.0f,4955.0f,5140.0f,5244.0f,5332.0f,5453.0f,5581.0f, 5686.0f,5774.0f,5911.0f,6168.0f,6585.0f,7091.0f,7533.0f,7774.0f, 7782.0f,7613.0f,7356.0f,7107.0f,6850.0f,6521.0f,6071.0f,5493.0f, 4842.0f,4224.0f,3710.0f,3276.0f,2867.0f,2401.0f,1871.0f,1276.0f, 674.0f,96.0f,-474.0f,-1157.0f,-1984.0f,-2940.0f,-3920.0f,-4739.0f, -5309.0f,-5614.0f,-5751.0f,-5855.0f,-5992.0f,-6144.0f,-6241.0f,-6265.0f, -6201.0f,-6104.0f,-6024.0f,-6008.0f,-6088.0f,-6265.0f,-6562.0f,-6916.0f, -7229.0f,-7389.0f,-7325.0f,-7012.0f,-6546.0f,-6032.0f,-5526.0f,-5044.0f, -4546.0f,-3992.0f,-3366.0f,-2699.0f,-2057.0f,-1510.0f,-1053.0f,-707.0f, -426.0f,-153.0f,120.0f,457.0f,843.0f,1228.0f,1598.0f,1983.0f, 2393.0f,2883.0f,3413.0f,3935.0f,4353.0f,4610.0f,4722.0f,4722.0f, 4666.0f,4577.0f,4473.0f,4385.0f,4385.0f,4537.0f,4867.0f,5300.0f, 5694.0f,5919.0f,5919.0f,5766.0f,5565.0f,5397.0f,5228.0f,4963.0f, 4513.0f,3863.0f,3084.0f,2353.0f,1799.0f,1469.0f,1349.0f,1341.0f, 1365.0f,1365.0f,1317.0f,1236.0f,1132.0f,1028.0f,907.0f,754.0f, 514.0f,160.0f,-274.0f,-763.0f,-1181.0f,-1438.0f,-1510.0f,-1438.0f, -1350.0f,-1414.0f,-1711.0f,-2217.0f,-2820.0f,-3366.0f,-3767.0f,-4024.0f, -4217.0f,-4490.0f,-4900.0f,-5438.0f,-6040.0f,-6586.0f,-7020.0f,-7269.0f, -7317.0f,-7189.0f,-6916.0f,-6570.0f,-6201.0f,-5871.0f,-5574.0f,-5285.0f, -4980.0f,-4643.0f,-4321.0f,-4040.0f,-3807.0f,-3591.0f,-3309.0f,-2860.0f, -2209.0f,-1382.0f,-458.0f,465.0f,1325.0f,2056.0f,2674.0f,3212.0f, 3710.0f,4152.0f,4561.0f,4875.0f,5091.0f,5212.0f,5316.0f,5477.0f, 5726.0f,6015.0f,6256.0f,6360.0f,6256.0f,6015.0f,5694.0f,5405.0f, 5172.0f,4939.0f,4626.0f,4192.0f,3662.0f,3132.0f,2738.0f,2529.0f, 2497.0f,2537.0f,2545.0f,2465.0f,2288.0f,2080.0f,1879.0f,1702.0f, 1533.0f,1341.0f,1092.0f,762.0f,369.0f,-57.0f,-490.0f,-884.0f, -1197.0f,-1406.0f,-1502.0f,-1534.0f,-1551.0f,-1591.0f,-1695.0f,-1832.0f, -1984.0f,-2129.0f,-2289.0f,-2498.0f,-2771.0f,-3101.0f,-3438.0f,-3719.0f, -3872.0f,-3904.0f,-3831.0f,-3711.0f,-3607.0f,-3566.0f,-3607.0f,-3711.0f, -3864.0f,-4000.0f,-4088.0f,-4105.0f,-4080.0f,-4008.0f,-3920.0f,-3823.0f, -3679.0f,-3446.0f,-3117.0f,-2691.0f,-2209.0f,-1719.0f,-1261.0f,-884.0f, -627.0f,-482.0f,-442.0f,-434.0f,-426.0f,-370.0f,-258.0f,-113.0f, 56.0f,257.0f,505.0f,811.0f,1188.0f,1630.0f,2112.0f,2674.0f, 3284.0f,3943.0f,4585.0f,5148.0f,5525.0f,5670.0f,5565.0f,5324.0f, 5067.0f,4915.0f,4915.0f,5043.0f,5236.0f,5405.0f,5477.0f,5421.0f, 5228.0f,4915.0f,4521.0f,4079.0f,3598.0f,3092.0f,2545.0f,1935.0f, 1244.0f,530.0f,-113.0f,-635.0f,-980.0f,-1157.0f,-1229.0f,-1302.0f, -1422.0f,-1623.0f,-1888.0f,-2169.0f,-2458.0f,-2715.0f,-2932.0f,-3133.0f, -3350.0f,-3615.0f,-3944.0f,-4297.0f,-4619.0f,-4795.0f,-4787.0f,-4578.0f, -4233.0f,-3848.0f,-3518.0f,-3301.0f,-3229.0f,-3245.0f,-3277.0f,-3245.0f, -3101.0f,-2876.0f,-2651.0f,-2506.0f,-2466.0f,-2490.0f,-2490.0f,-2386.0f, -2161.0f,-1872.0f,-1583.0f,-1318.0f,-1093.0f,-860.0f,-643.0f,-466.0f, -370.0f,-338.0f,-298.0f,-145.0f,176.0f,642.0f,1116.0f,1485.0f, 1686.0f,1815.0f,2015.0f,2393.0f,2947.0f,3525.0f,3927.0f,4015.0f, 3790.0f,3389.0f,3003.0f,2786.0f,2786.0f,2939.0f,3116.0f,3228.0f, 3212.0f,3108.0f,2947.0f,2810.0f,2730.0f,2714.0f,2746.0f,2770.0f, 2714.0f,2521.0f,2184.0f,1758.0f,1349.0f,1076.0f,1036.0f,1188.0f, 1413.0f,1550.0f,1477.0f,1188.0f,795.0f,441.0f,208.0f,88.0f, -1.0f,-177.0f,-482.0f,-884.0f,-1318.0f,-1743.0f,-2105.0f,-2410.0f, -2627.0f,-2739.0f,-2779.0f,-2811.0f,-2924.0f,-3173.0f,-3534.0f,-3920.0f, -4193.0f,-4321.0f,-4321.0f,-4257.0f,-4233.0f,-4265.0f,-4297.0f,-4257.0f, -4080.0f,-3751.0f,-3317.0f,-2836.0f,-2370.0f,-1944.0f,-1559.0f,-1221.0f, -908.0f,-619.0f,-346.0f,-97.0f,128.0f,345.0f,570.0f,819.0f, 1116.0f,1445.0f,1758.0f,2039.0f,2256.0f,2417.0f,2521.0f,2562.0f, 2505.0f,2345.0f,2104.0f,1823.0f,1566.0f,1389.0f,1309.0f,1301.0f, 1349.0f,1437.0f,1542.0f,1670.0f,1799.0f,1935.0f,2048.0f,2152.0f, 2240.0f,2272.0f,2216.0f,2039.0f,1718.0f,1325.0f,963.0f,722.0f, 634.0f,690.0f,811.0f,931.0f,1011.0f,1060.0f,1100.0f,1124.0f, 1156.0f,1172.0f,1164.0f,1092.0f,947.0f,706.0f,369.0f,-25.0f, -442.0f,-788.0f,-996.0f,-1053.0f,-980.0f,-868.0f,-788.0f,-804.0f, -908.0f,-1045.0f,-1149.0f,-1173.0f,-1165.0f,-1189.0f,-1342.0f,-1631.0f, -1992.0f,-2314.0f,-2482.0f,-2466.0f,-2306.0f,-2097.0f,-1936.0f,-1840.0f, -1808.0f,-1791.0f,-1791.0f,-1808.0f,-1864.0f,-1960.0f,-2057.0f,-2145.0f, -2217.0f,-2289.0f,-2378.0f,-2474.0f,-2514.0f,-2434.0f,-2185.0f,-1791.0f, -1342.0f,-964.0f,-723.0f,-643.0f,-627.0f,-571.0f,-386.0f,-65.0f, 321.0f,698.0f,1011.0f,1252.0f,1469.0f,1726.0f,2039.0f,2393.0f, 2746.0f,3059.0f,3324.0f,3541.0f,3710.0f,3798.0f,3790.0f,3662.0f, 3453.0f,3212.0f,3027.0f,2907.0f,2835.0f,2770.0f,2642.0f,2465.0f, 2256.0f,2056.0f,1903.0f,1774.0f,1654.0f,1493.0f,1301.0f,1044.0f, 746.0f,401.0f,24.0f,-346.0f,-675.0f,-924.0f,-1085.0f,-1173.0f, -1237.0f,-1326.0f,-1454.0f,-1591.0f,-1687.0f,-1727.0f,-1711.0f,-1679.0f, -1687.0f,-1767.0f,-1928.0f,-2137.0f,-2362.0f,-2546.0f,-2659.0f,-2683.0f, -2635.0f,-2554.0f,-2482.0f,-2474.0f,-2571.0f,-2747.0f,-2932.0f,-3028.0f, -2980.0f,-2787.0f,-2538.0f,-2330.0f,-2209.0f,-2145.0f,-2032.0f,-1751.0f, -1310.0f,-812.0f,-386.0f,-137.0f,-49.0f,-41.0f,0.0f,136.0f, 353.0f,570.0f,746.0f,875.0f,987.0f,1132.0f,1301.0f,1493.0f, 1670.0f,1831.0f,2015.0f,2232.0f,2481.0f,2706.0f,2819.0f,2786.0f, 2602.0f,2361.0f,2120.0f,1951.0f,1847.0f,1790.0f,1758.0f,1734.0f, 1702.0f,1662.0f,1614.0f,1582.0f,1582.0f,1614.0f,1670.0f,1694.0f, 1662.0f,1542.0f,1357.0f,1156.0f,987.0f,875.0f,819.0f,779.0f, 722.0f,658.0f,570.0f,473.0f,345.0f,200.0f,24.0f,-161.0f, -378.0f,-611.0f,-892.0f,-1221.0f,-1583.0f,-1952.0f,-2257.0f,-2482.0f, -2627.0f,-2691.0f,-2707.0f,-2715.0f,-2731.0f,-2755.0f,-2771.0f,-2763.0f, -2723.0f,-2651.0f,-2579.0f,-2538.0f,-2546.0f,-2579.0f,-2579.0f,-2498.0f, -2306.0f,-2040.0f,-1743.0f,-1470.0f,-1221.0f,-980.0f,-715.0f,-434.0f, -169.0f,32.0f,152.0f,224.0f,273.0f,305.0f,329.0f,345.0f, 369.0f,449.0f,618.0f,891.0f,1220.0f,1533.0f,1766.0f,1911.0f, 1983.0f,2023.0f,2064.0f,2088.0f,2080.0f,2023.0f,1927.0f,1839.0f, 1782.0f,1766.0f,1774.0f,1782.0f,1790.0f,1790.0f,1823.0f,1903.0f, 1991.0f,2056.0f,2064.0f,2015.0f,1895.0f,1758.0f,1614.0f,1461.0f, 1276.0f,1068.0f,835.0f,602.0f,393.0f,184.0f,-33.0f,-282.0f, -547.0f,-796.0f,-1012.0f,-1173.0f,-1302.0f,-1430.0f,-1567.0f,-1719.0f, -1864.0f,-1976.0f,-2016.0f,-2008.0f,-1968.0f,-1920.0f,-1880.0f,-1840.0f, -1791.0f,-1743.0f,-1679.0f,-1623.0f,-1583.0f,-1551.0f,-1543.0f,-1534.0f, -1510.0f,-1478.0f,-1438.0f,-1374.0f,-1318.0f,-1277.0f,-1253.0f,-1269.0f, -1286.0f,-1302.0f,-1277.0f,-1197.0f,-1069.0f,-908.0f,-755.0f,-643.0f, -603.0f,-611.0f,-627.0f,-571.0f,-402.0f,-137.0f,168.0f,457.0f, 682.0f,835.0f,979.0f,1140.0f,1349.0f,1566.0f,1758.0f,1895.0f, 1975.0f,2015.0f,2047.0f,2088.0f,2176.0f,2305.0f,2473.0f,2658.0f, 2794.0f,2843.0f,2770.0f,2578.0f,2321.0f,2072.0f,1863.0f,1686.0f, 1509.0f,1293.0f,1028.0f,730.0f,457.0f,232.0f,64.0f,-41.0f, -137.0f,-217.0f,-314.0f,-410.0f,-506.0f,-587.0f,-659.0f,-723.0f, -788.0f,-844.0f,-908.0f,-972.0f,-1020.0f,-1061.0f,-1069.0f,-1061.0f, -1045.0f,-1061.0f,-1117.0f,-1237.0f,-1390.0f,-1559.0f,-1695.0f,-1800.0f, -1888.0f,-1968.0f,-2048.0f,-2113.0f,-2145.0f,-2097.0f,-1976.0f,-1767.0f, -1526.0f,-1286.0f,-1077.0f,-916.0f,-796.0f,-699.0f,-603.0f,-506.0f, -410.0f,-338.0f,-298.0f,-290.0f,-314.0f,-314.0f,-274.0f,-145.0f, 72.0f,353.0f,650.0f,915.0f,1116.0f,1260.0f,1389.0f,1525.0f, 1654.0f,1750.0f,1758.0f,1654.0f,1461.0f,1228.0f,1011.0f,867.0f, 811.0f,811.0f,835.0f,843.0f,811.0f,746.0f,682.0f,642.0f, 634.0f,650.0f,658.0f,634.0f,586.0f,514.0f,449.0f,417.0f, 441.0f,530.0f,674.0f,835.0f,979.0f,1060.0f,1052.0f,963.0f, 811.0f,650.0f,505.0f,385.0f,265.0f,112.0f,-81.0f,-314.0f, -555.0f,-772.0f,-940.0f,-1053.0f,-1141.0f,-1213.0f,-1286.0f,-1350.0f, -1422.0f,-1478.0f,-1526.0f,-1559.0f,-1575.0f,-1567.0f,-1543.0f,-1494.0f, -1438.0f,-1382.0f,-1350.0f,-1334.0f,-1326.0f,-1286.0f,-1205.0f,-1069.0f, -908.0f,-739.0f,-619.0f,-539.0f,-498.0f,-466.0f,-418.0f,-346.0f, -241.0f,-129.0f,-9.0f,88.0f,176.0f,248.0f,313.0f,369.0f, 417.0f,457.0f,473.0f,481.0f,465.0f,433.0f,401.0f,369.0f, 345.0f,321.0f,321.0f,353.0f,409.0f,497.0f,594.0f,658.0f, 698.0f,722.0f,762.0f,851.0f,1003.0f,1188.0f,1349.0f,1445.0f, 1453.0f,1397.0f,1333.0f,1309.0f,1333.0f,1365.0f,1365.0f,1293.0f, 1132.0f,907.0f,658.0f,425.0f,208.0f,0.0f,-209.0f,-434.0f, -659.0f,-844.0f,-956.0f,-996.0f,-972.0f,-916.0f,-868.0f,-844.0f, -852.0f,-892.0f,-940.0f,-988.0f,-996.0f,-972.0f,-924.0f,-876.0f, -860.0f,-876.0f,-916.0f,-940.0f,-924.0f,-860.0f,-763.0f,-667.0f, -587.0f,-523.0f,-474.0f,-434.0f,-418.0f,-418.0f,-418.0f,-426.0f, -434.0f,-442.0f,-466.0f,-498.0f,-523.0f,-506.0f,-434.0f,-298.0f, -145.0f,-17.0f,32.0f,16.0f,-41.0f,-97.0f,-129.0f,-121.0f, -89.0f,-49.0f,0.0f,72.0f,192.0f,361.0f,578.0f,819.0f, 1036.0f,1228.0f,1373.0f,1477.0f,1550.0f,1582.0f,1582.0f,1533.0f, 1437.0f,1317.0f,1164.0f,1011.0f,859.0f,706.0f,570.0f,449.0f, 361.0f,281.0f,216.0f,136.0f,48.0f,-25.0f,-81.0f,-113.0f, -113.0f,-121.0f,-153.0f,-217.0f,-306.0f,-386.0f,-442.0f,-450.0f, -402.0f,-322.0f,-241.0f,-185.0f,-169.0f,-201.0f,-290.0f,-402.0f, -515.0f,-595.0f,-643.0f,-651.0f,-651.0f,-659.0f,-667.0f,-675.0f, -667.0f,-635.0f,-595.0f,-547.0f,-531.0f,-531.0f,-547.0f,-579.0f, -611.0f,-643.0f,-683.0f,-723.0f,-763.0f,-780.0f,-780.0f,-747.0f, -675.0f,-587.0f,-490.0f,-394.0f,-298.0f,-193.0f,-73.0f,40.0f, 168.0f,281.0f,353.0f,385.0f,377.0f,353.0f,329.0f,305.0f, 305.0f,305.0f,313.0f,313.0f,289.0f,248.0f,192.0f,136.0f, 80.0f,40.0f,8.0f,-17.0f,-65.0f,-129.0f,-177.0f,-185.0f, -161.0f,-105.0f,-57.0f,-17.0f,8.0f,48.0f,104.0f,192.0f, 297.0f,401.0f,497.0f,578.0f,650.0f,714.0f,779.0f,835.0f, 899.0f,955.0f,1003.0f,1019.0f,979.0f,875.0f,714.0f,522.0f, 337.0f,192.0f,88.0f,0.0f,-73.0f,-177.0f,-306.0f,-434.0f, -539.0f,-611.0f,-635.0f,-627.0f,-603.0f,-603.0f,-627.0f,-691.0f, -780.0f,-876.0f,-948.0f,-988.0f,-980.0f,-940.0f,-884.0f,-828.0f, -780.0f,-715.0f,-619.0f,-482.0f,-314.0f,-153.0f,-17.0f,64.0f, 88.0f,88.0f,64.0f,40.0f,32.0f,24.0f,8.0f,-9.0f, -49.0f,-97.0f,-137.0f,-153.0f,-129.0f,-73.0f,8.0f,96.0f, 160.0f,192.0f,184.0f,160.0f,152.0f,192.0f,273.0f,385.0f, 514.0f,634.0f,730.0f,803.0f,867.0f,931.0f,987.0f,1044.0f, 1068.0f,1060.0f,995.0f,891.0f,754.0f,586.0f,409.0f,232.0f, 72.0f,-49.0f,-129.0f,-161.0f,-161.0f,-153.0f,-153.0f,-169.0f, -225.0f,-306.0f,-394.0f,-474.0f,-555.0f,-619.0f,-675.0f,-731.0f, -780.0f,-804.0f,-812.0f,-788.0f,-723.0f,-643.0f,-531.0f,-410.0f, -274.0f,-137.0f,-17.0f,72.0f,136.0f,168.0f,176.0f,176.0f, 168.0f,160.0f,128.0f,80.0f,16.0f,-49.0f,-113.0f,-177.0f, -233.0f,-290.0f,-354.0f,-434.0f,-506.0f,-563.0f,-611.0f,-635.0f, -659.0f,-691.0f,-723.0f,-763.0f,-780.0f,-747.0f,-659.0f,-539.0f, -386.0f,-249.0f,-145.0f,-73.0f,-25.0f,16.0f,80.0f,160.0f, 248.0f,329.0f,393.0f,441.0f,473.0f,497.0f,530.0f,546.0f, 554.0f,546.0f,522.0f,489.0f,433.0f,361.0f,281.0f,208.0f, 152.0f,120.0f,112.0f,128.0f,152.0f,168.0f,176.0f,184.0f, 192.0f,216.0f,240.0f,248.0f,257.0f,248.0f,240.0f,240.0f, 232.0f,208.0f,160.0f,104.0f,48.0f,24.0f,24.0f,48.0f, 72.0f,80.0f,64.0f,32.0f,-9.0f,-57.0f,-121.0f,-185.0f, -274.0f,-354.0f,-426.0f,-490.0f,-555.0f,-619.0f,-691.0f,-747.0f, -796.0f,-812.0f,-812.0f,-812.0f,-804.0f,-796.0f,-772.0f,-723.0f, -643.0f,-563.0f,-482.0f,-410.0f,-322.0f,-209.0f,-65.0f,88.0f, 232.0f,337.0f,393.0f,401.0f,385.0f,345.0f,313.0f,273.0f, 224.0f,176.0f,120.0f,56.0f,-17.0f,-89.0f,-145.0f,-177.0f, -169.0f,-121.0f,-65.0f,0.0f,56.0f,104.0f,136.0f,144.0f, 136.0f,112.0f,96.0f,104.0f,136.0f,184.0f,240.0f,297.0f, 337.0f,377.0f,417.0f,465.0f,530.0f,586.0f,626.0f,650.0f, 650.0f,634.0f,602.0f,562.0f,505.0f,433.0f,345.0f,265.0f, 192.0f,152.0f,120.0f,96.0f,56.0f,-1.0f,-89.0f,-177.0f, -274.0f,-362.0f,-458.0f,-563.0f,-683.0f,-804.0f,-908.0f,-980.0f, -1012.0f,-996.0f,-924.0f,-804.0f,-635.0f,-450.0f,-266.0f,-105.0f, -1.0f,40.0f,48.0f,32.0f,16.0f,-1.0f,-17.0f,-49.0f, -73.0f,-113.0f,-145.0f,-177.0f,-193.0f,-209.0f,-201.0f,-185.0f, -145.0f,-97.0f,-49.0f,-17.0f,-17.0f,-25.0f,-49.0f,-49.0f, -41.0f,-1.0f,40.0f,96.0f,144.0f,184.0f,224.0f,281.0f, 337.0f,393.0f,441.0f,465.0f,473.0f,465.0f,457.0f,433.0f, 417.0f,393.0f,361.0f,337.0f,329.0f,337.0f,353.0f,361.0f, 345.0f,313.0f,257.0f,184.0f,104.0f,8.0f,-81.0f,-185.0f, -282.0f,-362.0f,-418.0f,-466.0f,-515.0f,-563.0f,-595.0f,-611.0f, -595.0f,-563.0f,-523.0f,-482.0f,-450.0f,-402.0f,-330.0f,-233.0f, -145.0f,-73.0f,-25.0f,0.0f,32.0f,88.0f,168.0f,240.0f, 305.0f,321.0f,297.0f,232.0f,144.0f,40.0f,-49.0f,-153.0f, -233.0f,-314.0f,-378.0f,-442.0f,-498.0f,-555.0f,-595.0f,-603.0f, -571.0f,-498.0f,-418.0f,-346.0f,-306.0f,-290.0f,-290.0f,-282.0f, -241.0f,-177.0f,-89.0f,0.0f,80.0f,144.0f,200.0f,248.0f, 305.0f,337.0f,353.0f,345.0f,321.0f,289.0f,273.0f,265.0f, 273.0f,281.0f,265.0f,224.0f,160.0f,88.0f,32.0f,24.0f, 48.0f,104.0f,144.0f,152.0f,112.0f,32.0f,-41.0f,-97.0f, -121.0f,-105.0f,-89.0f,-89.0f,-105.0f,-129.0f,-153.0f,-153.0f, -129.0f,-65.0f,16.0f,104.0f,192.0f,257.0f,289.0f,289.0f, 257.0f,208.0f,152.0f,104.0f,56.0f,0.0f,-73.0f,-161.0f, -249.0f,-330.0f,-378.0f,-394.0f,-402.0f,-426.0f,-474.0f,-547.0f, -611.0f,-643.0f,-635.0f,-587.0f,-506.0f,-434.0f,-370.0f,-322.0f, -266.0f,-193.0f,-97.0f,16.0f,152.0f,273.0f,361.0f,401.0f, 393.0f,369.0f,329.0f,313.0f,313.0f,305.0f,281.0f,232.0f, 152.0f,88.0f,40.0f,16.0f,16.0f,24.0f,24.0f,8.0f, -9.0f,-41.0f,-97.0f,-169.0f,-241.0f,-314.0f,-370.0f,-394.0f, -402.0f,-402.0f,-386.0f,-362.0f,-306.0f,-217.0f,-121.0f,-17.0f, 56.0f,112.0f,160.0f,216.0f,289.0f,361.0f,417.0f,441.0f, 425.0f,409.0f,401.0f,441.0f,497.0f,554.0f,570.0f,538.0f, 465.0f,377.0f,297.0f,216.0f,144.0f,64.0f,-17.0f,-97.0f, -169.0f,-233.0f,-282.0f,-338.0f,-378.0f,-394.0f,-378.0f,-330.0f, -258.0f,-177.0f,-113.0f,-81.0f,-73.0f,-65.0f,-57.0f,-41.0f, -33.0f,-33.0f,-57.0f,-89.0f,-121.0f,-137.0f,-137.0f,-137.0f, -161.0f,-209.0f,-274.0f,-338.0f,-378.0f,-402.0f,-410.0f,-418.0f, -434.0f,-458.0f,-498.0f,-523.0f,-531.0f,-515.0f,-458.0f,-394.0f, -322.0f,-274.0f,-249.0f,-249.0f,-241.0f,-217.0f,-161.0f,-81.0f, 0.0f,88.0f,160.0f,216.0f,257.0f,289.0f,313.0f,353.0f, 401.0f,473.0f,546.0f,586.0f,586.0f,554.0f,489.0f,417.0f, 353.0f,305.0f,257.0f,200.0f,136.0f,56.0f,-1.0f,-41.0f, -73.0f,-105.0f,-137.0f,-185.0f,-225.0f,-258.0f,-266.0f,-258.0f, -241.0f,-217.0f,-185.0f,-145.0f,-73.0f,8.0f,120.0f,224.0f, 329.0f,425.0f,497.0f,554.0f,578.0f,562.0f,505.0f,425.0f, 313.0f,208.0f,112.0f,16.0f,-81.0f,-185.0f,-282.0f,-370.0f, -434.0f,-474.0f,-506.0f,-531.0f,-555.0f,-571.0f,-579.0f,-555.0f, -531.0f,-506.0f,-498.0f,-515.0f,-539.0f,-555.0f,-539.0f,-490.0f, -410.0f,-322.0f,-241.0f,-185.0f,-153.0f,-145.0f,-145.0f,-129.0f, -89.0f,-41.0f,16.0f,72.0f,120.0f,152.0f,168.0f,176.0f, 192.0f,216.0f,248.0f,273.0f,273.0f,240.0f,184.0f,104.0f, 24.0f,-49.0f,-113.0f,-169.0f,-209.0f,-241.0f,-258.0f,-258.0f, -225.0f,-153.0f,-57.0f,48.0f,168.0f,281.0f,369.0f,441.0f, 489.0f,522.0f,522.0f,505.0f,457.0f,385.0f,305.0f,216.0f, 128.0f,56.0f,0.0f,-25.0f,-57.0f,-81.0f,-105.0f,-145.0f, -201.0f,-266.0f,-322.0f,-362.0f,-378.0f,-386.0f,-394.0f,-418.0f, -450.0f,-474.0f,-474.0f,-442.0f,-378.0f,-298.0f,-217.0f,-145.0f, -89.0f,-33.0f,0.0f,56.0f,96.0f,136.0f,160.0f,176.0f, 192.0f,224.0f,257.0f,305.0f,345.0f,361.0f,345.0f,313.0f, 257.0f,192.0f,128.0f,72.0f,16.0f,-25.0f,-81.0f,-153.0f, -233.0f,-306.0f,-362.0f,-386.0f,-378.0f,-346.0f,-314.0f,-298.0f, -290.0f,-298.0f,-298.0f,-290.0f,-258.0f,-201.0f,-129.0f,-49.0f, 16.0f,88.0f,136.0f,176.0f,216.0f,257.0f,305.0f,353.0f, 401.0f,441.0f,457.0f,441.0f,409.0f,361.0f,305.0f,240.0f, 168.0f,88.0f,24.0f,-25.0f,-65.0f,-89.0f,-97.0f,-121.0f, -145.0f,-177.0f,-193.0f,-201.0f,-185.0f,-169.0f,-145.0f,-121.0f, -97.0f,-65.0f,-41.0f,-17.0f,-1.0f,-1.0f,8.0f,24.0f, 48.0f,64.0f,64.0f,32.0f,-17.0f,-73.0f,-121.0f,-153.0f, -169.0f,-193.0f,-225.0f,-258.0f,-282.0f,-298.0f,-298.0f,-306.0f, -306.0f,-322.0f,-338.0f,-346.0f,-346.0f,-346.0f,-354.0f,-378.0f, -402.0f,-418.0f,-418.0f,-402.0f,-346.0f,-282.0f,-193.0f,-105.0f, -17.0f,64.0f,136.0f,192.0f,248.0f,305.0f,353.0f,401.0f, 441.0f,449.0f,425.0f,369.0f,297.0f,224.0f,168.0f,120.0f, 88.0f,56.0f,24.0f,-25.0f,-81.0f,-145.0f,-201.0f,-249.0f, -282.0f,-306.0f,-314.0f,-322.0f,-314.0f,-290.0f,-266.0f,-225.0f, -177.0f,-113.0f,-49.0f,16.0f,80.0f,136.0f,176.0f,208.0f, 216.0f,208.0f,192.0f,176.0f,160.0f,144.0f,128.0f,128.0f, 128.0f,144.0f,168.0f,184.0f,192.0f,176.0f,136.0f,80.0f, 16.0f,-41.0f,-89.0f,-129.0f,-169.0f,-217.0f,-282.0f,-338.0f, -378.0f,-394.0f,-378.0f,-330.0f,-274.0f,-225.0f,-193.0f,-161.0f, -137.0f,-105.0f,-65.0f,-25.0f,16.0f,64.0f,96.0f,120.0f, 128.0f,136.0f,144.0f,136.0f,120.0f,88.0f,56.0f,8.0f, -25.0f,-65.0f,-97.0f,-137.0f,-169.0f,-217.0f,-258.0f,-290.0f, -306.0f,-290.0f,-249.0f,-185.0f,-137.0f,-105.0f,-105.0f,-121.0f, -153.0f,-169.0f,-153.0f,-113.0f,-41.0f,32.0f,104.0f,152.0f, 184.0f,208.0f,232.0f,257.0f,289.0f,313.0f,313.0f,289.0f, 257.0f,216.0f,176.0f,144.0f,112.0f,80.0f,32.0f,-1.0f, -41.0f,-73.0f,-89.0f,-105.0f,-121.0f,-137.0f,-153.0f,-169.0f, -169.0f,-169.0f,-161.0f,-153.0f,-137.0f,-121.0f,-89.0f,-65.0f, -41.0f,-17.0f,8.0f,40.0f,80.0f,120.0f,144.0f,152.0f, 144.0f,120.0f,88.0f,64.0f,56.0f,64.0f,72.0f,80.0f, 56.0f,24.0f,-17.0f,-65.0f,-113.0f,-145.0f,-185.0f,-217.0f, -266.0f,-314.0f,-362.0f,-402.0f,-434.0f,-458.0f,-466.0f,-466.0f, -450.0f,-410.0f,-354.0f,-282.0f,-201.0f,-121.0f,-33.0f,32.0f, 104.0f,168.0f,216.0f,265.0f,289.0f,305.0f,297.0f,289.0f, 273.0f,240.0f,208.0f,176.0f,136.0f,112.0f,88.0f,72.0f, 56.0f,32.0f,0.0f,-33.0f,-73.0f,-105.0f,-121.0f,-129.0f, -129.0f,-121.0f,-121.0f,-121.0f,-113.0f,-105.0f,-97.0f,-89.0f, -73.0f,-49.0f,-25.0f,-9.0f,8.0f,24.0f,48.0f,80.0f, 104.0f,120.0f,128.0f,120.0f,120.0f,128.0f,144.0f,160.0f, 176.0f,168.0f,136.0f,80.0f,8.0f,-65.0f,-145.0f,-225.0f, -298.0f,-346.0f,-386.0f,-402.0f,-410.0f,-418.0f,-410.0f,-402.0f, -370.0f,-314.0f,-241.0f,-169.0f,-105.0f,-57.0f,-25.0f,0.0f, 16.0f,32.0f,40.0f,40.0f,32.0f,24.0f,16.0f,16.0f, 32.0f,48.0f,48.0f,40.0f,16.0f,-17.0f,-57.0f,-89.0f, -121.0f,-137.0f,-161.0f,-169.0f,-177.0f,-177.0f,-177.0f,-177.0f, -177.0f,-193.0f,-209.0f,-225.0f,-233.0f,-225.0f,-217.0f,-193.0f, -161.0f,-121.0f,-65.0f,-1.0f,64.0f,128.0f,184.0f,216.0f, 248.0f,281.0f,313.0f,345.0f,369.0f,369.0f,361.0f,329.0f, 289.0f,257.0f,224.0f,192.0f,152.0f,104.0f,48.0f,-1.0f, -49.0f,-89.0f,-129.0f,-161.0f,-201.0f,-241.0f,-274.0f,-298.0f, -314.0f,-314.0f,-306.0f,-282.0f,-258.0f,-225.0f,-201.0f,-177.0f, -153.0f,-121.0f,-73.0f,-25.0f,16.0f,56.0f,80.0f,88.0f, 72.0f,56.0f,40.0f,40.0f,48.0f,56.0f,48.0f,24.0f, -1.0f,-41.0f,-81.0f,-121.0f,-153.0f,-177.0f,-217.0f,-249.0f, -266.0f,-266.0f,-249.0f,-209.0f,-169.0f,-137.0f,-113.0f,-89.0f, -65.0f,-25.0f,8.0f,48.0f,80.0f,112.0f,136.0f,152.0f, 168.0f,176.0f,176.0f,184.0f,192.0f,200.0f,216.0f,224.0f, 216.0f,208.0f,184.0f,160.0f,144.0f,144.0f,136.0f,120.0f, 80.0f,32.0f,-25.0f,-73.0f,-121.0f,-145.0f,-161.0f,-185.0f, -209.0f,-241.0f,-282.0f,-298.0f,-298.0f,-274.0f,-233.0f,-185.0f, -129.0f,-73.0f,-17.0f,24.0f,64.0f,96.0f,120.0f,144.0f, 160.0f,176.0f,168.0f,152.0f,104.0f,56.0f,8.0f,-25.0f, -57.0f,-89.0f,-121.0f,-169.0f,-209.0f,-233.0f,-258.0f,-274.0f, -298.0f,-330.0f,-354.0f,-362.0f,-354.0f,-314.0f,-258.0f,-193.0f, -145.0f,-97.0f,-65.0f,-41.0f,-17.0f,-1.0f,16.0f,32.0f, 40.0f,48.0f,64.0f,80.0f,104.0f,136.0f,160.0f,184.0f, 208.0f,224.0f,232.0f,232.0f,232.0f,224.0f,208.0f,184.0f, 144.0f,88.0f,24.0f,-49.0f,-121.0f,-193.0f,-249.0f,-290.0f, -322.0f,-330.0f,-338.0f,-322.0f,-298.0f,-249.0f,-201.0f,-145.0f, -89.0f,-41.0f,0.0f,48.0f,88.0f,128.0f,160.0f,176.0f, 184.0f,184.0f,176.0f,152.0f,120.0f,96.0f,72.0f,64.0f, 64.0f,72.0f,72.0f,56.0f,24.0f,-1.0f,-49.0f,-89.0f, -121.0f,-145.0f,-169.0f,-185.0f,-201.0f,-209.0f,-201.0f,-185.0f, -169.0f,-161.0f,-153.0f,-145.0f,-137.0f,-121.0f,-97.0f,-65.0f, -25.0f,0.0f,24.0f,40.0f,48.0f,48.0f,48.0f,48.0f, 48.0f,48.0f,40.0f,24.0f,8.0f,-17.0f,-41.0f,-73.0f, -105.0f,-129.0f,-153.0f,-177.0f,-193.0f,-209.0f,-209.0f,-209.0f, -209.0f,-201.0f,-193.0f,-185.0f,-169.0f,-145.0f,-113.0f,-81.0f, -49.0f,-25.0f,-1.0f,16.0f,48.0f,88.0f,112.0f,136.0f, 152.0f,168.0f,184.0f,208.0f,224.0f,240.0f,232.0f,208.0f, 168.0f,120.0f,80.0f,32.0f,-1.0f,-49.0f,-97.0f,-153.0f, -225.0f,-314.0f,-394.0f,-474.0f,-539.0f,-579.0f,-595.0f,-571.0f, -531.0f,-482.0f,-418.0f,-354.0f,-290.0f,-225.0f,-169.0f,-113.0f, -57.0f,-9.0f,32.0f,72.0f,104.0f,120.0f,136.0f,128.0f, 120.0f,112.0f,96.0f,88.0f,80.0f,80.0f,88.0f,96.0f, 96.0f,104.0f,104.0f,104.0f,96.0f,88.0f,80.0f,64.0f, 48.0f,24.0f,0.0f,-9.0f,-9.0f,-9.0f,-1.0f,0.0f, 8.0f,16.0f,32.0f,56.0f,88.0f,112.0f,136.0f,160.0f, 176.0f,192.0f,208.0f,232.0f,257.0f,273.0f,281.0f,273.0f, 248.0f,216.0f,168.0f,112.0f,56.0f,0.0f,-49.0f,-97.0f, -153.0f,-201.0f,-249.0f,-290.0f,-314.0f,-330.0f,-330.0f,-314.0f, -282.0f,-249.0f,-217.0f,-193.0f,-161.0f,-121.0f,-65.0f,-9.0f, 40.0f,80.0f,104.0f,96.0f,88.0f,80.0f,72.0f,72.0f, 80.0f,80.0f,80.0f,72.0f,72.0f,64.0f,48.0f,24.0f, 0.0f,-25.0f,-49.0f,-81.0f,-121.0f,-169.0f,-225.0f,-274.0f, -306.0f,-322.0f,-322.0f,-314.0f,-314.0f,-314.0f,-314.0f,-298.0f, -258.0f,-209.0f,-145.0f,-97.0f,-49.0f,-9.0f,24.0f,64.0f, 120.0f,160.0f,192.0f,208.0f,208.0f,208.0f,200.0f,192.0f, 184.0f,168.0f,136.0f,112.0f,80.0f,56.0f,32.0f,0.0f, -25.0f,-65.0f,-105.0f,-145.0f,-177.0f,-201.0f,-217.0f,-225.0f, -225.0f,-217.0f,-209.0f,-193.0f,-177.0f,-161.0f,-145.0f,-121.0f, -89.0f,-41.0f,8.0f,48.0f,80.0f,88.0f,80.0f,80.0f, 80.0f,104.0f,128.0f,144.0f,144.0f,120.0f,88.0f,56.0f, 32.0f,16.0f,-1.0f,-25.0f,-57.0f,-97.0f,-137.0f,-185.0f, -225.0f,-258.0f,-282.0f,-290.0f,-274.0f,-249.0f,-209.0f,-169.0f, -129.0f,-97.0f,-57.0f,-17.0f,24.0f,72.0f,104.0f,120.0f, 120.0f,120.0f,120.0f,120.0f,112.0f,104.0f,80.0f,56.0f, 48.0f,40.0f,56.0f,72.0f,80.0f,80.0f,64.0f,32.0f, -1.0f,-41.0f,-73.0f,-113.0f,-145.0f,-185.0f,-217.0f,-249.0f, -274.0f,-282.0f,-274.0f,-258.0f,-233.0f,-201.0f,-177.0f,-145.0f, -105.0f,-57.0f,-9.0f,32.0f,72.0f,112.0f,136.0f,152.0f, 168.0f,176.0f,184.0f,184.0f,184.0f,176.0f,144.0f,104.0f, 56.0f,8.0f,-33.0f,-65.0f,-97.0f,-121.0f,-153.0f,-185.0f, -217.0f,-249.0f,-266.0f,-258.0f,-241.0f,-201.0f,-169.0f,-145.0f, -137.0f,-137.0f,-145.0f,-153.0f,-153.0f,-153.0f,-145.0f,-121.0f, -89.0f,-57.0f,-33.0f,-9.0f,8.0f,24.0f,48.0f,72.0f, 96.0f,112.0f,120.0f,112.0f,104.0f,104.0f,96.0f,96.0f, 72.0f,40.0f,-1.0f,-57.0f,-105.0f,-137.0f,-153.0f,-161.0f, -177.0f,-185.0f,-201.0f,-193.0f,-169.0f,-129.0f,-81.0f,-41.0f, -17.0f,0.0f,32.0f,64.0f,104.0f,136.0f,168.0f,184.0f, 184.0f,184.0f,168.0f,152.0f,120.0f,88.0f,64.0f,32.0f, 16.0f,8.0f,0.0f,0.0f,-1.0f,-9.0f,-25.0f,-49.0f, -81.0f,-121.0f,-169.0f,-217.0f,-258.0f,-282.0f,-290.0f,-282.0f, -266.0f,-258.0f,-241.0f,-233.0f,-209.0f,-169.0f,-121.0f,-65.0f, -17.0f,16.0f,40.0f,64.0f,88.0f,112.0f,136.0f,152.0f, 160.0f,160.0f,144.0f,128.0f,104.0f,72.0f,32.0f,-1.0f, -33.0f,-49.0f,-57.0f,-57.0f,-73.0f,-97.0f,-121.0f,-145.0f, -161.0f,-153.0f,-145.0f,-121.0f,-97.0f,-81.0f,-73.0f,-65.0f, -57.0f,-49.0f,-33.0f,-17.0f,-9.0f,-1.0f,0.0f,8.0f, 24.0f,48.0f,72.0f,96.0f,120.0f,128.0f,136.0f,136.0f, 128.0f,120.0f,104.0f,80.0f,40.0f,8.0f,-33.0f,-81.0f, -129.0f,-177.0f,-217.0f,-249.0f,-266.0f,-282.0f,-274.0f,-274.0f, -258.0f,-241.0f,-217.0f,-185.0f,-145.0f,-97.0f,-49.0f,-9.0f, 16.0f,32.0f,48.0f,56.0f,56.0f,64.0f,72.0f,80.0f, 88.0f,96.0f,112.0f,120.0f,112.0f,104.0f,72.0f,48.0f, 16.0f,-1.0f,-17.0f,-33.0f,-41.0f,-65.0f,-89.0f,-121.0f, -145.0f,-169.0f,-177.0f,-177.0f,-169.0f,-169.0f,-169.0f,-169.0f, -161.0f,-153.0f,-129.0f,-113.0f,-81.0f,-49.0f,-17.0f,24.0f, 64.0f,104.0f,128.0f,144.0f,144.0f,144.0f,136.0f,128.0f, 120.0f,96.0f,64.0f,24.0f,-1.0f,-41.0f,-81.0f,-121.0f, -169.0f,-201.0f,-225.0f,-241.0f,-233.0f,-225.0f,-217.0f,-217.0f, -217.0f,-225.0f,-225.0f,-217.0f,-193.0f,-161.0f,-129.0f,-97.0f, -73.0f,-49.0f,-25.0f,-1.0f,24.0f,56.0f,88.0f,112.0f, 128.0f,136.0f,144.0f,152.0f,152.0f,152.0f,152.0f,152.0f, 152.0f,152.0f,144.0f,112.0f,64.0f,8.0f,-33.0f,-73.0f, -97.0f,-121.0f,-145.0f,-169.0f,-193.0f,-217.0f,-225.0f,-209.0f, -185.0f,-153.0f,-113.0f,-65.0f,-25.0f,8.0f,40.0f,56.0f, 64.0f,56.0f,48.0f,40.0f,40.0f,40.0f,48.0f,56.0f, 56.0f,48.0f,32.0f,16.0f,0.0f,-25.0f,-41.0f,-57.0f, -73.0f,-81.0f,-97.0f,-121.0f,-161.0f,-185.0f,-193.0f,-161.0f, -113.0f,-49.0f, 0 }; t_CKUINT mandpluk_size = 4450; // data for marmstk1.raw... SAMPLE marmstk1_data[] = { 16.0f,-113.0f,522.0f,-1237.0f,2056.0f,5525.0f,-7413.0f,-659.0f, 562.0f,1076.0f,923.0f,-2153.0f,3357.0f,-4434.0f,-2900.0f,4433.0f, 1212.0f,987.0f,-772.0f,-1671.0f,3951.0f,-7325.0f,7710.0f,-9702.0f, 12601.0f,-11919.0f,6754.0f,2521.0f,-8594.0f,10047.0f,-11437.0f,11773.0f, -9992.0f,5140.0f,738.0f,-2081.0f,570.0f,803.0f,-531.0f,-1848.0f, 3067.0f,-3566.0f,7059.0f,-11630.0f,10384.0f,-5398.0f,939.0f,3116.0f, -5430.0f,7172.0f,-7839.0f,5999.0f,-860.0f,-539.0f,-1382.0f,2634.0f, -4048.0f,2345.0f,-699.0f,-17.0f,2626.0f,-6169.0f,7565.0f,-5647.0f, 1092.0f,3646.0f,-4177.0f,3887.0f,-4466.0f,2256.0f,1373.0f,-4129.0f, 4393.0f,-812.0f,-3101.0f,4481.0f,-4611.0f,4063.0f,-2635.0f,-1101.0f, 5493.0f,-6385.0f,4963.0f,-1390.0f,-940.0f,1011.0f,-2603.0f,2329.0f, 883.0f,-2474.0f,3614.0f,-2506.0f,-1422.0f,2064.0f,-3261.0f,4513.0f, -2828.0f,1550.0f,738.0f,-3044.0f,2313.0f,-1197.0f,-161.0f,1678.0f, -1398.0f,1381.0f,-796.0f,-1310.0f,2706.0f,-3093.0f,1293.0f,1212.0f, -2008.0f,2650.0f,-2297.0f,1220.0f,289.0f,-2554.0f,3084.0f,-1591.0f, 313.0f,666.0f,-1061.0f,714.0f,-699.0f,-1085.0f,3349.0f,-2940.0f, 1734.0f,-49.0f,-2306.0f,3590.0f,-3414.0f,3814.0f,-2434.0f,-145.0f, 2015.0f,-2972.0f,1863.0f,-498.0f,-338.0f,642.0f,8.0f,-563.0f, 2144.0f,-3928.0f,3461.0f,-1687.0f,-796.0f,2819.0f,-3269.0f,3999.0f, -3237.0f,1252.0f,1124.0f,-2338.0f,1293.0f,-563.0f,-49.0f,1028.0f, -908.0f,433.0f,441.0f,-2747.0f,3397.0f,-2024.0f,883.0f,1196.0f, -2579.0f,2923.0f,-2964.0f,1140.0f,634.0f,-2297.0f,3365.0f,-2322.0f, 1301.0f,666.0f,-2579.0f,2128.0f,-1502.0f,907.0f,393.0f,-611.0f, 514.0f,-354.0f,-1406.0f,2039.0f,-1077.0f,152.0f,923.0f,-2217.0f, 2553.0f,-2065.0f,1285.0f,401.0f,-1719.0f,2433.0f,-2081.0f,1124.0f, 449.0f,-1454.0f,1389.0f,-1551.0f,650.0f,674.0f,-1310.0f,1598.0f, -844.0f,-555.0f,1260.0f,-1840.0f,2023.0f,-466.0f,-755.0f,1702.0f, -2289.0f,1437.0f,-547.0f,72.0f,1108.0f,-1302.0f,690.0f,-338.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT marmstk1_size = 256; // data for ooo.raw... SAMPLE ooo_data[] = { -153.0f,473.0f,-209.0f,-924.0f,-739.0f,-587.0f,-868.0f,-1077.0f, -1221.0f,-1358.0f,-1077.0f,-707.0f,-932.0f,-1526.0f,-1751.0f,-1286.0f, -932.0f,-1551.0f,-2346.0f,-2217.0f,-2346.0f,-4627.0f,-7863.0f,-8883.0f, -7004.0f,-5566.0f,-6851.0f,-6843.0f,-1366.0f,4674.0f,4618.0f,2931.0f, 6617.0f,11316.0f,10063.0f,6376.0f,5951.0f,7669.0f,8449.0f,6360.0f, 3067.0f,3276.0f,6007.0f,4577.0f,-884.0f,-3309.0f,-2410.0f,-4482.0f, -9309.0f,-11823.0f,-11927.0f,-11405.0f,-10843.0f,-10875.0f,-10200.0f,-7486.0f, -4795.0f,-4072.0f,-3711.0f,-2450.0f,-1318.0f,-547.0f,273.0f,754.0f, 979.0f,2072.0f,3606.0f,3646.0f,2730.0f,3067.0f,4095.0f,3670.0f, 1871.0f,795.0f,1325.0f,1566.0f,-121.0f,-1936.0f,-1567.0f,-635.0f, -1775.0f,-3615.0f,-3526.0f,-2426.0f,-2538.0f,-3358.0f,-3109.0f,-1599.0f, -466.0f,-611.0f,-707.0f,144.0f, 0 }; t_CKUINT ooo_size = 92; // data for peksblnk.raw... SAMPLE peksblnk_data[] = { 0.0f,32.0f,152.0f,353.0f,626.0f,979.0f,1413.0f,1919.0f, 2489.0f,3148.0f,3871.0f,4658.0f,5525.0f,6449.0f,7437.0f,8489.0f, 9597.0f,10762.0f,11982.0f,13243.0f,14560.0f,15926.0f,17323.0f,18753.0f, 20231.0f,21732.0f,23250.0f,24800.0f,26375.0f,27957.0f,29555.0f,31153.0f, 32767.0f,31153.0f,29555.0f,27957.0f,26375.0f,24800.0f,23250.0f,21732.0f, 20231.0f,18753.0f,17323.0f,15926.0f,14560.0f,13243.0f,11982.0f,10762.0f, 9597.0f,8489.0f,7437.0f,6449.0f,5525.0f,4658.0f,3871.0f,3148.0f, 2489.0f,1919.0f,1413.0f,979.0f,626.0f,353.0f,152.0f,32.0f, 0.0f,-33.0f,-153.0f,-354.0f,-627.0f,-980.0f,-1414.0f,-1920.0f, -2490.0f,-3149.0f,-3872.0f,-4659.0f,-5526.0f,-6442.0f,-7438.0f,-8482.0f, -9598.0f,-10763.0f,-11983.0f,-13244.0f,-14561.0f,-15927.0f,-17316.0f,-18754.0f, -20232.0f,-21725.0f,-23251.0f,-24801.0f,-26376.0f,-27958.0f,-29556.0f,-31154.0f, -32768.0f,-31154.0f,-29556.0f,-27958.0f,-26376.0f,-24801.0f,-23251.0f,-21725.0f, -20232.0f,-18754.0f,-17316.0f,-15927.0f,-14561.0f,-13244.0f,-11983.0f,-10763.0f, -9598.0f,-8482.0f,-7438.0f,-6442.0f,-5526.0f,-4659.0f,-3872.0f,-3149.0f, -2490.0f,-1920.0f,-1414.0f,-980.0f,-627.0f,-354.0f,-153.0f,-33.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT peksblnk_size = 256; // data for ppksblnk.raw... SAMPLE ppksblnk_data[] = { 0.0f,32.0f,152.0f,353.0f,626.0f,979.0f,1413.0f,1919.0f, 2489.0f,3148.0f,3871.0f,4658.0f,5525.0f,6449.0f,7437.0f,8489.0f, 9597.0f,10762.0f,11982.0f,13243.0f,14560.0f,15926.0f,17323.0f,18753.0f, 20231.0f,21732.0f,23250.0f,24800.0f,26375.0f,27957.0f,29555.0f,31153.0f, 32767.0f,31153.0f,29555.0f,27957.0f,26375.0f,24800.0f,23250.0f,21732.0f, 20231.0f,18753.0f,17323.0f,15926.0f,14560.0f,13243.0f,11982.0f,10762.0f, 9597.0f,8489.0f,7437.0f,6449.0f,5525.0f,4658.0f,3871.0f,3148.0f, 2489.0f,1919.0f,1413.0f,979.0f,626.0f,353.0f,152.0f,32.0f, 0.0f,32.0f,152.0f,353.0f,626.0f,979.0f,1413.0f,1919.0f, 2489.0f,3148.0f,3871.0f,4658.0f,5525.0f,6449.0f,7437.0f,8489.0f, 9597.0f,10762.0f,11982.0f,13243.0f,14560.0f,15926.0f,17323.0f,18753.0f, 20231.0f,21732.0f,23250.0f,24800.0f,26375.0f,27957.0f,29555.0f,31153.0f, 32767.0f,31153.0f,29555.0f,27957.0f,26375.0f,24800.0f,23250.0f,21732.0f, 20231.0f,18753.0f,17323.0f,15926.0f,14560.0f,13243.0f,11982.0f,10762.0f, 9597.0f,8489.0f,7437.0f,6449.0f,5525.0f,4658.0f,3871.0f,3148.0f, 2489.0f,1919.0f,1413.0f,979.0f,626.0f,353.0f,152.0f,32.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT ppksblnk_size = 256; // data for silence.raw... SAMPLE silence_data[] = { 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT silence_size = 224; // data for sineblnk.raw... SAMPLE sineblnk_data[] = { 0.0f,1606.0f,3212.0f,4802.0f,6392.0f,7967.0f,9509.0f,11035.0f, 12536.0f,14014.0f,15444.0f,16841.0f,18207.0f,19516.0f,20785.0f,22005.0f, 23170.0f,24278.0f,25330.0f,26318.0f,27242.0f,28109.0f,28896.0f,29619.0f, 30278.0f,30848.0f,31354.0f,31788.0f,32141.0f,32414.0f,32615.0f,32727.0f, 32767.0f,32727.0f,32615.0f,32414.0f,32141.0f,31788.0f,31354.0f,30848.0f, 30278.0f,29619.0f,28896.0f,28109.0f,27242.0f,26318.0f,25330.0f,24278.0f, 23170.0f,22005.0f,20785.0f,19516.0f,18207.0f,16841.0f,15444.0f,14014.0f, 12536.0f,11035.0f,9509.0f,7967.0f,6392.0f,4802.0f,3212.0f,1606.0f, 0.0f,-1607.0f,-3213.0f,-4803.0f,-6385.0f,-7968.0f,-9510.0f,-11036.0f, -12537.0f,-14015.0f,-15445.0f,-16842.0f,-18208.0f,-19517.0f,-20786.0f,-22006.0f, -23171.0f,-24279.0f,-25331.0f,-26319.0f,-27243.0f,-28110.0f,-28897.0f,-29620.0f, -30271.0f,-30849.0f,-31355.0f,-31789.0f,-32142.0f,-32415.0f,-32616.0f,-32728.0f, -32768.0f,-32728.0f,-32616.0f,-32415.0f,-32142.0f,-31789.0f,-31355.0f,-30849.0f, -30271.0f,-29620.0f,-28897.0f,-28110.0f,-27243.0f,-26319.0f,-25331.0f,-24279.0f, -23171.0f,-22006.0f,-20786.0f,-19517.0f,-18208.0f,-16842.0f,-15445.0f,-14015.0f, -12537.0f,-11036.0f,-9510.0f,-7968.0f,-6385.0f,-4803.0f,-3213.0f,-1607.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT sineblnk_size = 256; // data for sinewave.raw... SAMPLE sinewave_data[] = { 0.0f,803.0f,1606.0f,2409.0f,3212.0f,4015.0f,4802.0f,5605.0f, 6392.0f,7180.0f,7967.0f,8738.0f,9509.0f,10272.0f,11035.0f,11798.0f, 12536.0f,13275.0f,14014.0f,14729.0f,15444.0f,16151.0f,16841.0f,17532.0f, 18207.0f,18865.0f,19516.0f,20158.0f,20785.0f,21403.0f,22005.0f,22592.0f, 23170.0f,23732.0f,24278.0f,24808.0f,25330.0f,25828.0f,26318.0f,26784.0f, 27242.0f,27684.0f,28109.0f,28511.0f,28896.0f,29266.0f,29619.0f,29957.0f, 30278.0f,30575.0f,30848.0f,31113.0f,31354.0f,31579.0f,31788.0f,31972.0f, 32141.0f,32286.0f,32414.0f,32527.0f,32615.0f,32679.0f,32727.0f,32759.0f, 32767.0f,32759.0f,32727.0f,32679.0f,32615.0f,32527.0f,32414.0f,32286.0f, 32141.0f,31972.0f,31788.0f,31579.0f,31354.0f,31113.0f,30848.0f,30575.0f, 30278.0f,29957.0f,29619.0f,29266.0f,28896.0f,28511.0f,28109.0f,27684.0f, 27242.0f,26784.0f,26318.0f,25828.0f,25330.0f,24808.0f,24278.0f,23732.0f, 23170.0f,22592.0f,22005.0f,21403.0f,20785.0f,20158.0f,19516.0f,18865.0f, 18207.0f,17532.0f,16841.0f,16151.0f,15444.0f,14729.0f,14014.0f,13275.0f, 12536.0f,11798.0f,11035.0f,10272.0f,9509.0f,8738.0f,7967.0f,7180.0f, 6392.0f,5605.0f,4802.0f,4015.0f,3212.0f,2409.0f,1606.0f,803.0f, 0.0f,-804.0f,-1607.0f,-2410.0f,-3213.0f,-4016.0f,-4803.0f,-5606.0f, -6385.0f,-7181.0f,-7968.0f,-8739.0f,-9510.0f,-10273.0f,-11036.0f,-11791.0f, -12537.0f,-13276.0f,-14015.0f,-14730.0f,-15445.0f,-16152.0f,-16842.0f,-17533.0f, -18208.0f,-18866.0f,-19517.0f,-20159.0f,-20786.0f,-21404.0f,-22006.0f,-22593.0f, -23171.0f,-23733.0f,-24279.0f,-24809.0f,-25331.0f,-25829.0f,-26319.0f,-26785.0f, -27243.0f,-27685.0f,-28110.0f,-28512.0f,-28897.0f,-29267.0f,-29620.0f,-29958.0f, -30271.0f,-30576.0f,-30849.0f,-31114.0f,-31355.0f,-31580.0f,-31789.0f,-31973.0f, -32142.0f,-32287.0f,-32415.0f,-32520.0f,-32616.0f,-32680.0f,-32728.0f,-32760.0f, -32768.0f,-32760.0f,-32728.0f,-32680.0f,-32616.0f,-32520.0f,-32415.0f,-32287.0f, -32142.0f,-31973.0f,-31789.0f,-31580.0f,-31355.0f,-31114.0f,-30849.0f,-30576.0f, -30271.0f,-29958.0f,-29620.0f,-29267.0f,-28897.0f,-28512.0f,-28110.0f,-27685.0f, -27243.0f,-26785.0f,-26319.0f,-25829.0f,-25331.0f,-24809.0f,-24279.0f,-23733.0f, -23171.0f,-22593.0f,-22006.0f,-21404.0f,-20786.0f,-20159.0f,-19517.0f,-18866.0f, -18208.0f,-17533.0f,-16842.0f,-16152.0f,-15445.0f,-14730.0f,-14015.0f,-13276.0f, -12537.0f,-11791.0f,-11036.0f,-10273.0f,-9510.0f,-8739.0f,-7968.0f,-7181.0f, -6385.0f,-5606.0f,-4803.0f,-4016.0f,-3213.0f,-2410.0f,-1607.0f,-804.0f, 0 }; t_CKUINT sinewave_size = 256; // data for snglpeak.raw... SAMPLE snglpeak_data[] = { 0.0f,8.0f,32.0f,88.0f,152.0f,240.0f,353.0f,481.0f, 626.0f,795.0f,979.0f,1188.0f,1413.0f,1654.0f,1919.0f,2192.0f, 2489.0f,2810.0f,3148.0f,3501.0f,3871.0f,4256.0f,4658.0f,5083.0f, 5525.0f,5983.0f,6449.0f,6931.0f,7437.0f,7959.0f,8489.0f,9035.0f, 9597.0f,10175.0f,10762.0f,11364.0f,11982.0f,12601.0f,13243.0f,13902.0f, 14560.0f,15235.0f,15926.0f,16616.0f,17323.0f,18038.0f,18753.0f,19492.0f, 20231.0f,20969.0f,21732.0f,22495.0f,23250.0f,24029.0f,24800.0f,25587.0f, 26375.0f,27162.0f,27957.0f,28752.0f,29555.0f,30358.0f,31153.0f,31964.0f, 32767.0f,31964.0f,31153.0f,30358.0f,29555.0f,28752.0f,27957.0f,27162.0f, 26375.0f,25587.0f,24800.0f,24029.0f,23250.0f,22495.0f,21732.0f,20969.0f, 20231.0f,19492.0f,18753.0f,18038.0f,17323.0f,16616.0f,15926.0f,15235.0f, 14560.0f,13902.0f,13243.0f,12601.0f,11982.0f,11364.0f,10762.0f,10175.0f, 9597.0f,9035.0f,8489.0f,7959.0f,7437.0f,6931.0f,6449.0f,5983.0f, 5525.0f,5083.0f,4658.0f,4256.0f,3871.0f,3501.0f,3148.0f,2810.0f, 2489.0f,2192.0f,1919.0f,1654.0f,1413.0f,1188.0f,979.0f,795.0f, 626.0f,481.0f,353.0f,240.0f,152.0f,88.0f,32.0f,8.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT snglpeak_size = 256; // data for twopeaks.raw... SAMPLE twopeaks_data[] = { 0.0f,8.0f,32.0f,88.0f,152.0f,240.0f,353.0f,481.0f, 626.0f,795.0f,979.0f,1188.0f,1413.0f,1654.0f,1919.0f,2192.0f, 2489.0f,2810.0f,3148.0f,3501.0f,3871.0f,4256.0f,4658.0f,5083.0f, 5525.0f,5983.0f,6449.0f,6931.0f,7437.0f,7959.0f,8489.0f,9035.0f, 9597.0f,10175.0f,10762.0f,11364.0f,11982.0f,12601.0f,13243.0f,13902.0f, 14560.0f,15235.0f,15926.0f,16616.0f,17323.0f,18038.0f,18753.0f,19492.0f, 20231.0f,20969.0f,21732.0f,22495.0f,23250.0f,24029.0f,24800.0f,25587.0f, 26375.0f,27162.0f,27957.0f,28752.0f,29555.0f,30358.0f,31153.0f,31964.0f, 32767.0f,31964.0f,31153.0f,30358.0f,29555.0f,28752.0f,27957.0f,27162.0f, 26375.0f,25587.0f,24800.0f,24029.0f,23250.0f,22495.0f,21732.0f,20969.0f, 20231.0f,19492.0f,18753.0f,18038.0f,17323.0f,16616.0f,15926.0f,15235.0f, 14560.0f,13902.0f,13243.0f,12601.0f,11982.0f,11364.0f,10762.0f,10175.0f, 9597.0f,9035.0f,8489.0f,7959.0f,7437.0f,6931.0f,6449.0f,5983.0f, 5525.0f,5083.0f,4658.0f,4256.0f,3871.0f,3501.0f,3148.0f,2810.0f, 2489.0f,2192.0f,1919.0f,1654.0f,1413.0f,1188.0f,979.0f,795.0f, 626.0f,481.0f,353.0f,240.0f,152.0f,88.0f,32.0f,8.0f, 0.0f,-9.0f,-33.0f,-81.0f,-153.0f,-241.0f,-354.0f,-482.0f, -627.0f,-796.0f,-980.0f,-1189.0f,-1414.0f,-1655.0f,-1920.0f,-2193.0f, -2490.0f,-2811.0f,-3149.0f,-3502.0f,-3872.0f,-4249.0f,-4659.0f,-5084.0f, -5526.0f,-5984.0f,-6442.0f,-6932.0f,-7438.0f,-7960.0f,-8482.0f,-9036.0f, -9598.0f,-10176.0f,-10763.0f,-11365.0f,-11983.0f,-12602.0f,-13244.0f,-13903.0f, -14561.0f,-15236.0f,-15927.0f,-16609.0f,-17316.0f,-18039.0f,-18754.0f,-19485.0f, -20232.0f,-20970.0f,-21725.0f,-22488.0f,-23251.0f,-24030.0f,-24801.0f,-25588.0f, -26376.0f,-27163.0f,-27958.0f,-28753.0f,-29556.0f,-30359.0f,-31154.0f,-31965.0f, -32768.0f,-31965.0f,-31154.0f,-30359.0f,-29556.0f,-28753.0f,-27958.0f,-27163.0f, -26376.0f,-25588.0f,-24801.0f,-24030.0f,-23251.0f,-22488.0f,-21725.0f,-20970.0f, -20232.0f,-19485.0f,-18754.0f,-18039.0f,-17316.0f,-16609.0f,-15927.0f,-15236.0f, -14561.0f,-13903.0f,-13244.0f,-12602.0f,-11983.0f,-11365.0f,-10763.0f,-10176.0f, -9598.0f,-9036.0f,-8482.0f,-7960.0f,-7438.0f,-6932.0f,-6442.0f,-5984.0f, -5526.0f,-5084.0f,-4659.0f,-4249.0f,-3872.0f,-3502.0f,-3149.0f,-2811.0f, -2490.0f,-2193.0f,-1920.0f,-1655.0f,-1414.0f,-1189.0f,-980.0f,-796.0f, -627.0f,-482.0f,-354.0f,-241.0f,-153.0f,-81.0f,-33.0f,-9.0f, 0 }; t_CKUINT twopeaks_size = 256; // data for glot_ahh.raw... SAMPLE glot_ahh_data[] = { -1.0f,1.0f,2.0f,3.0f,5.0f,6.0f,5.0f,5.0f, 4.0f,1.0f,-3.0f,-10.0f,-16.0f,-24.0f,-29.0f,-36.0f, -46.0f,-50.0f,-57.0f,-61.0f,-65.0f,-67.0f,-68.0f,-70.0f, -69.0f,-67.0f,-65.0f,-60.0f,-56.0f,-52.0f,-46.0f,-41.0f, -37.0f,-31.0f,-25.0f,-20.0f,-16.0f,-9.0f,-4.0f,-2.0f, 1.0f,8.0f,6.0f,9.0f,7.0f,5.0f,3.0f,3.0f, 0.0f,-3.0f,-13.0f,-12.0f,-16.0f,-16.0f,-13.0f,-8.0f, 3.0f,20.0f,36.0f,58.0f,77.0f,92.0f,100.0f,103.0f, 99.0f,91.0f,88.0f,100.0f,135.0f,215.0f,354.0f,563.0f, 854.0f,1217.0f,1654.0f,2143.0f,2664.0f,3188.0f,3683.0f,4092.0f, 4411.0f,4612.0f,4685.0f,4633.0f,4458.0f,4190.0f,3860.0f,3492.0f, 3117.0f,2764.0f,2426.0f,2124.0f,1834.0f,1545.0f,1226.0f,843.0f, 376.0f,-209.0f,-918.0f,-1762.0f,-2733.0f,-3793.0f,-4925.0f,-6085.0f, -7225.0f,-8300.0f,-9248.0f,-10045.0f,-10659.0f,-11069.0f,-11275.0f,-11283.0f, -11106.0f,-10786.0f,-10351.0f,-9850.0f,-9311.0f,-8762.0f,-8218.0f,-7692.0f, -7180.0f,-6670.0f,-6135.0f,-5549.0f,-4884.0f,-4113.0f,-3236.0f,-2232.0f, -1111.0f,108.0f,1405.0f,2743.0f,4082.0f,5379.0f,6597.0f,7699.0f, 8660.0f,9454.0f,10074.0f,10513.0f,10769.0f,10863.0f,10817.0f,10647.0f, 10378.0f,10029.0f,9627.0f,9186.0f,8728.0f,8256.0f,7767.0f,7251.0f, 6711.0f,6120.0f,5474.0f,4754.0f,3949.0f,3055.0f,2079.0f,1042.0f, -41.0f,-1130.0f,-2193.0f,-3187.0f,-4080.0f,-4834.0f,-5433.0f,-5857.0f, -6113.0f,-6216.0f,-6182.0f,-6045.0f,-5836.0f,-5578.0f,-5312.0f,-5062.0f, -4836.0f,-4641.0f,-4479.0f,-4330.0f,-4189.0f,-4039.0f,-3861.0f,-3639.0f, -3357.0f,-3015.0f,-2618.0f,-2170.0f,-1692.0f,-1193.0f,-698.0f,-240.0f, 168.0f,498.0f,751.0f,905.0f,971.0f,952.0f,864.0f,727.0f, 569.0f,411.0f,271.0f,179.0f,145.0f,189.0f,296.0f,481.0f, 729.0f,1028.0f,1365.0f,1714.0f,2058.0f,2384.0f,2679.0f,2934.0f, 3143.0f,3301.0f,3428.0f,3525.0f,3612.0f,3703.0f,3798.0f,3921.0f, 4074.0f,4256.0f,4469.0f,4692.0f,4912.0f,5116.0f,5271.0f,5365.0f, 5373.0f,5274.0f,5063.0f,4734.0f,4296.0f,3758.0f,3137.0f,2459.0f, 1756.0f,1045.0f,360.0f,-282.0f,-867.0f,-1386.0f,-1847.0f,-2256.0f, -2623.0f,-2971.0f,-3306.0f,-3652.0f,-4016.0f,-4401.0f,-4796.0f,-5194.0f, -5579.0f,-5926.0f,-6221.0f,-6438.0f,-6557.0f,-6565.0f,-6460.0f,-6242.0f, -5916.0f,-5505.0f,-5008.0f,-4459.0f,-3871.0f,-3274.0f,-2679.0f,-2103.0f, -1557.0f,-1046.0f,-582.0f,-154.0f,235.0f,596.0f,935.0f,1258.0f, 1577.0f,1892.0f,2208.0f,2522.0f,2834.0f,3133.0f,3414.0f,3657.0f, 3856.0f,3995.0f,4063.0f,4065.0f,3986.0f,3839.0f,3618.0f,3345.0f, 3035.0f,2701.0f,2362.0f,2033.0f,1725.0f,1452.0f,1222.0f,1041.0f, 898.0f,794.0f,719.0f,663.0f,617.0f,564.0f,494.0f,401.0f, 280.0f,127.0f,-54.0f,-259.0f,-477.0f,-698.0f,-908.0f,-1093.0f, -1246.0f,-1360.0f,-1431.0f,-1462.0f,-1465.0f,-1445.0f,-1424.0f,-1410.0f, -1418.0f,-1471.0f,-1565.0f,-1710.0f,-1899.0f,-2123.0f,-2372.0f,-2630.0f, -2886.0f,-3108.0f,-3297.0f,-3435.0f,-3519.0f,-3542.0f,-3515.0f,-3428.0f, -3303.0f,-3144.0f,-2960.0f,-2769.0f,-2565.0f,-2369.0f,-2173.0f,-1986.0f, -1803.0f,-1624.0f,-1440.0f,-1240.0f,-1021.0f,-778.0f,-502.0f,-191.0f, 152.0f,525.0f,921.0f,1331.0f,1745.0f,2139.0f,2508.0f,2840.0f, 3115.0f,3335.0f,3491.0f,3577.0f,3601.0f,3571.0f,3495.0f,3385.0f, 3245.0f,3090.0f,2936.0f,2779.0f,2630.0f,2489.0f,2345.0f,2201.0f, 2047.0f,1875.0f,1675.0f,1442.0f,1169.0f,862.0f,516.0f,146.0f, -236.0f,-621.0f,-995.0f,-1343.0f,-1649.0f,-1908.0f,-2112.0f,-2259.0f, -2355.0f,-2401.0f,-2405.0f,-2384.0f,-2340.0f,-2289.0f,-2235.0f,-2185.0f, -2141.0f,-2106.0f,-2071.0f,-2036.0f,-1996.0f,-1942.0f,-1868.0f,-1775.0f, -1653.0f,-1503.0f,-1336.0f,-1141.0f,-935.0f,-719.0f,-504.0f,-300.0f, -112.0f,55.0f,194.0f,306.0f,380.0f,432.0f,459.0f,468.0f, 466.0f,463.0f,465.0f,477.0f,509.0f,558.0f,627.0f,721.0f, 831.0f,950.0f,1076.0f,1197.0f,1311.0f,1411.0f,1490.0f,1552.0f, 1588.0f,1600.0f,1599.0f,1583.0f,1561.0f,1531.0f,1508.0f,1491.0f, 1481.0f,1481.0f,1494.0f,1506.0f,1523.0f,1530.0f,1528.0f,1502.0f, 1453.0f,1372.0f,1256.0f,1106.0f,923.0f,715.0f,486.0f,244.0f, 1.0f,-238.0f,-462.0f,-667.0f,-845.0f,-998.0f,-1124.0f,-1228.0f, -1314.0f,-1387.0f,-1451.0f,-1515.0f,-1581.0f,-1650.0f,-1723.0f,-1793.0f, -1863.0f,-1925.0f,-1969.0f,-2000.0f,-1997.0f,-1971.0f,-1908.0f,-1811.0f, -1686.0f,-1523.0f,-1342.0f,-1136.0f,-923.0f,-698.0f,-482.0f,-269.0f, -75.0f,107.0f,265.0f,400.0f,520.0f,622.0f,713.0f,793.0f, 873.0f,954.0f,1036.0f,1121.0f,1210.0f,1303.0f,1388.0f,1468.0f, 1527.0f,1572.0f,1588.0f,1581.0f,1539.0f,1473.0f,1380.0f,1270.0f, 1141.0f,1008.0f,873.0f,741.0f,621.0f,515.0f,427.0f,352.0f, 292.0f,245.0f,203.0f,167.0f,129.0f,86.0f,37.0f,-23.0f, -92.0f,-169.0f,-252.0f,-336.0f,-420.0f,-497.0f,-568.0f,-626.0f, -668.0f,-699.0f,-716.0f,-723.0f,-720.0f,-718.0f,-710.0f,-711.0f, -715.0f,-730.0f,-755.0f,-794.0f,-839.0f,-892.0f,-955.0f,-1010.0f, -1066.0f,-1112.0f,-1141.0f,-1162.0f,-1156.0f,-1138.0f,-1098.0f,-1041.0f, -972.0f,-891.0f,-805.0f,-713.0f,-628.0f,-546.0f,-471.0f,-402.0f, -342.0f,-288.0f,-231.0f,-176.0f,-119.0f,-51.0f,27.0f,116.0f, 214.0f,324.0f,438.0f,558.0f,670.0f,780.0f,876.0f,957.0f, 1019.0f,1062.0f,1080.0f,1076.0f,1055.0f,1019.0f,968.0f,909.0f, 843.0f,779.0f,712.0f,653.0f,597.0f,541.0f,488.0f,439.0f, 383.0f,324.0f,255.0f,177.0f,91.0f,-6.0f,-117.0f,-230.0f, -345.0f,-462.0f,-571.0f,-673.0f,-759.0f,-831.0f,-883.0f,-922.0f, -944.0f,-950.0f,-943.0f,-931.0f,-911.0f,-887.0f,-866.0f,-844.0f, -826.0f,-811.0f,-795.0f,-780.0f,-765.0f,-746.0f,-719.0f,-685.0f, -645.0f,-595.0f,-535.0f,-467.0f,-396.0f,-319.0f,-241.0f,-169.0f, -98.0f,-36.0f,16.0f,59.0f,90.0f,115.0f,131.0f,140.0f, 146.0f,155.0f,168.0f,184.0f,209.0f,242.0f,281.0f,328.0f, 379.0f,434.0f,483.0f,528.0f,567.0f,595.0f,610.0f,614.0f, 611.0f,595.0f,575.0f,551.0f,528.0f,505.0f,485.0f,470.0f, 466.0f,462.0f,460.0f,462.0f,465.0f,459.0f,449.0f,433.0f, 406.0f,369.0f,318.0f,257.0f,187.0f,110.0f,28.0f,-56.0f, -136.0f,-214.0f,-284.0f,-347.0f,-398.0f,-440.0f,-475.0f,-501.0f, -524.0f,-537.0f,-554.0f,-566.0f,-581.0f,-593.0f,-610.0f,-623.0f, -637.0f,-647.0f,-654.0f,-652.0f,-644.0f,-627.0f,-598.0f,-559.0f, -505.0f,-451.0f,-379.0f,-307.0f,-228.0f,-154.0f,-76.0f,-6.0f, 63.0f,119.0f,169.0f,214.0f,252.0f,282.0f,312.0f,343.0f, 373.0f,408.0f,443.0f,484.0f,526.0f,565.0f,604.0f,636.0f, 666.0f,680.0f,685.0f,678.0f,659.0f,624.0f,580.0f,532.0f, 479.0f,422.0f,366.0f,318.0f,272.0f,235.0f,205.0f,180.0f, 160.0f,143.0f,126.0f,110.0f,91.0f,67.0f,36.0f,3.0f, -36.0f,-78.0f,-123.0f,-167.0f,-212.0f,-248.0f,-286.0f,-315.0f, -339.0f,-354.0f,-368.0f,-375.0f,-380.0f,-385.0f,-385.0f,-390.0f, -393.0f,-401.0f,-410.0f,-422.0f,-433.0f,-446.0f,-457.0f,-468.0f, -476.0f,-476.0f,-474.0f,-467.0f,-454.0f,-433.0f,-406.0f,-376.0f, -337.0f,-297.0f,-254.0f,-212.0f,-168.0f,-128.0f,-89.0f,-55.0f, -24.0f,3.0f,28.0f,50.0f,72.0f,93.0f,117.0f,143.0f, 171.0f,203.0f,238.0f,275.0f,314.0f,349.0f,383.0f,411.0f, 431.0f,445.0f,446.0f,437.0f,420.0f,398.0f,365.0f,328.0f, 289.0f,251.0f,214.0f,180.0f,152.0f,126.0f,105.0f,85.0f, 62.0f,42.0f,19.0f,-8.0f,-41.0f,-77.0f,-116.0f,-159.0f, -203.0f,-247.0f,-290.0f,-328.0f,-363.0f,-392.0f,-415.0f,-430.0f, -440.0f,-439.0f,-436.0f,-431.0f,-419.0f,-401.0f,-387.0f,-370.0f, -356.0f,-344.0f,-330.0f,-322.0f,-316.0f,-310.0f,-303.0f,-297.0f, -285.0f,-271.0f,-255.0f,-231.0f,-205.0f,-176.0f,-143.0f,-110.0f, -81.0f,-49.0f,-22.0f,-5.0f,15.0f,23.0f,31.0f,33.0f, 36.0f,35.0f,37.0f,38.0f,46.0f,53.0f,69.0f,85.0f, 106.0f,125.0f,146.0f,164.0f,184.0f,196.0f,204.0f,208.0f, 207.0f,202.0f,193.0f,184.0f,174.0f,165.0f,158.0f,154.0f, 153.0f,156.0f,163.0f,171.0f,174.0f,179.0f,174.0f,165.0f, 149.0f,125.0f,91.0f,56.0f,18.0f,-22.0f,-54.0f,-82.0f, -100.0f,-105.0f,-102.0f,-90.0f,-72.0f,-52.0f,-29.0f,-9.0f, 4.0f,14.0f,18.0f,19.0f,11.0f,9.0f,0.0f,-2.0f, -8.0f,-8.0f,-7.0f,-7.0f,-4.0f,-2.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,0.0f,-1.0f,-1.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f, 0 }; t_CKUINT glot_ahh_size = 992; // data for glot_eee.raw... SAMPLE glot_eee_data[] = { 0.0f, -2.0f,-3.0f,1.0f,-1.0f,4.0f,4.0f,4.0f,3.0f, 1.0f,-2.0f,-6.0f,-13.0f,-20.0f,-27.0f,-31.0f,-40.0f, -43.0f,-45.0f,-44.0f,-46.0f,-45.0f,-42.0f,-45.0f,-45.0f, -46.0f,-48.0f,-52.0f,-51.0f,-55.0f,-58.0f,-57.0f,-54.0f, -54.0f,-51.0f,-49.0f,-47.0f,-44.0f,-42.0f,-43.0f,-42.0f, -43.0f,-46.0f,-42.0f,-43.0f,-40.0f,-38.0f,-34.0f,-29.0f, -29.0f,-27.0f,-26.0f,-24.0f,-25.0f,-26.0f,-27.0f,-32.0f, -31.0f,-35.0f,-33.0f,-34.0f,-31.0f,-32.0f,-28.0f,-27.0f, -26.0f,-20.0f,-20.0f,-20.0f,-19.0f,-20.0f,-26.0f,-27.0f, -35.0f,-40.0f,-46.0f,-49.0f,-50.0f,-53.0f,-51.0f,-46.0f, -43.0f,-38.0f,-29.0f,-23.0f,-20.0f,-13.0f,-11.0f,-7.0f, -9.0f,-10.0f,-10.0f,-13.0f,-17.0f,-15.0f,-19.0f,-16.0f, -14.0f,-11.0f,-9.0f,-5.0f,-2.0f,1.0f,3.0f,6.0f, 6.0f,6.0f,4.0f,4.0f,0.0f,1.0f,-1.0f,0.0f, -2.0f,-1.0f,-2.0f,0.0f,-2.0f,-3.0f,-4.0f,-7.0f, -9.0f,-14.0f,-14.0f,-19.0f,-23.0f,-22.0f,-21.0f,-19.0f, -17.0f,-11.0f,-9.0f,-2.0f,-1.0f,4.0f,7.0f,8.0f, 6.0f,7.0f,6.0f,4.0f,1.0f,-1.0f,-8.0f,-11.0f, -17.0f,-22.0f,-25.0f,-29.0f,-31.0f,-28.0f,-25.0f,-18.0f, -4.0f,8.0f,29.0f,39.0f,43.0f,36.0f,12.0f,-26.0f, -75.0f,-119.0f,-154.0f,-154.0f,-98.0f,19.0f,213.0f,476.0f, 796.0f,1141.0f,1468.0f,1733.0f,1891.0f,1903.0f,1747.0f,1429.0f, 971.0f,434.0f,-115.0f,-594.0f,-926.0f,-1045.0f,-922.0f,-560.0f, -6.0f,669.0f,1359.0f,1967.0f,2389.0f,2567.0f,2467.0f,2118.0f, 1579.0f,942.0f,321.0f,-186.0f,-498.0f,-576.0f,-427.0f,-103.0f, 309.0f,714.0f,1013.0f,1133.0f,1050.0f,774.0f,358.0f,-100.0f, -516.0f,-788.0f,-855.0f,-701.0f,-351.0f,129.0f,641.0f,1067.0f, 1325.0f,1338.0f,1089.0f,601.0f,-60.0f,-792.0f,-1472.0f,-2013.0f, -2326.0f,-2378.0f,-2174.0f,-1766.0f,-1241.0f,-692.0f,-214.0f,116.0f, 255.0f,193.0f,-43.0f,-396.0f,-807.0f,-1201.0f,-1527.0f,-1744.0f, -1852.0f,-1851.0f,-1786.0f,-1692.0f,-1613.0f,-1581.0f,-1609.0f,-1698.0f, -1832.0f,-1976.0f,-2101.0f,-2168.0f,-2157.0f,-2071.0f,-1904.0f,-1687.0f, -1450.0f,-1232.0f,-1067.0f,-993.0f,-1012.0f,-1138.0f,-1351.0f,-1628.0f, -1942.0f,-2240.0f,-2502.0f,-2686.0f,-2775.0f,-2764.0f,-2657.0f,-2471.0f, -2234.0f,-1973.0f,-1718.0f,-1498.0f,-1328.0f,-1224.0f,-1183.0f,-1204.0f, -1271.0f,-1372.0f,-1491.0f,-1618.0f,-1734.0f,-1839.0f,-1932.0f,-2006.0f, -2069.0f,-2123.0f,-2163.0f,-2190.0f,-2206.0f,-2196.0f,-2160.0f,-2095.0f, -1989.0f,-1844.0f,-1662.0f,-1446.0f,-1199.0f,-941.0f,-671.0f,-415.0f, -183.0f,12.0f,152.0f,224.0f,232.0f,161.0f,31.0f,-147.0f, -345.0f,-526.0f,-665.0f,-728.0f,-685.0f,-532.0f,-266.0f,96.0f, 529.0f,982.0f,1419.0f,1797.0f,2085.0f,2266.0f,2340.0f,2328.0f, 2255.0f,2153.0f,2068.0f,2014.0f,2011.0f,2061.0f,2145.0f,2243.0f, 2332.0f,2387.0f,2404.0f,2385.0f,2351.0f,2341.0f,2380.0f,2506.0f, 2730.0f,3054.0f,3457.0f,3901.0f,4322.0f,4673.0f,4897.0f,4963.0f, 4865.0f,4618.0f,4261.0f,3855.0f,3466.0f,3149.0f,2956.0f,2900.0f, 2983.0f,3173.0f,3431.0f,3711.0f,3962.0f,4142.0f,4240.0f,4254.0f, 4198.0f,4098.0f,3988.0f,3889.0f,3817.0f,3775.0f,3747.0f,3718.0f, 3657.0f,3542.0f,3358.0f,3108.0f,2806.0f,2475.0f,2149.0f,1866.0f, 1663.0f,1549.0f,1549.0f,1637.0f,1801.0f,1996.0f,2190.0f,2344.0f, 2427.0f,2407.0f,2286.0f,2063.0f,1748.0f,1380.0f,975.0f,565.0f, 181.0f,-162.0f,-448.0f,-671.0f,-838.0f,-949.0f,-1018.0f,-1053.0f, -1060.0f,-1052.0f,-1036.0f,-1020.0f,-1006.0f,-1000.0f,-1000.0f,-1024.0f, -1070.0f,-1144.0f,-1256.0f,-1409.0f,-1604.0f,-1840.0f,-2106.0f,-2393.0f, -2681.0f,-2951.0f,-3182.0f,-3354.0f,-3459.0f,-3487.0f,-3434.0f,-3321.0f, -3163.0f,-2978.0f,-2796.0f,-2637.0f,-2523.0f,-2464.0f,-2474.0f,-2544.0f, -2671.0f,-2840.0f,-3031.0f,-3232.0f,-3419.0f,-3588.0f,-3719.0f,-3805.0f, -3846.0f,-3840.0f,-3785.0f,-3687.0f,-3551.0f,-3385.0f,-3197.0f,-2998.0f, -2798.0f,-2610.0f,-2444.0f,-2312.0f,-2219.0f,-2170.0f,-2163.0f,-2205.0f, -2279.0f,-2378.0f,-2487.0f,-2592.0f,-2688.0f,-2754.0f,-2781.0f,-2759.0f, -2687.0f,-2565.0f,-2398.0f,-2190.0f,-1950.0f,-1695.0f,-1434.0f,-1191.0f, -972.0f,-787.0f,-649.0f,-558.0f,-518.0f,-527.0f,-569.0f,-640.0f, -723.0f,-799.0f,-868.0f,-906.0f,-911.0f,-874.0f,-793.0f,-671.0f, -515.0f,-325.0f,-115.0f,107.0f,331.0f,541.0f,729.0f,892.0f, 1012.0f,1089.0f,1120.0f,1104.0f,1052.0f,962.0f,856.0f,741.0f, 629.0f,533.0f,463.0f,436.0f,447.0f,505.0f,602.0f,735.0f, 895.0f,1071.0f,1249.0f,1416.0f,1565.0f,1679.0f,1759.0f,1791.0f, 1782.0f,1729.0f,1638.0f,1519.0f,1381.0f,1236.0f,1099.0f,970.0f, 872.0f,806.0f,773.0f,782.0f,830.0f,902.0f,1006.0f,1123.0f, 1242.0f,1355.0f,1453.0f,1526.0f,1564.0f,1566.0f,1528.0f,1451.0f, 1342.0f,1201.0f,1039.0f,870.0f,701.0f,543.0f,403.0f,293.0f, 213.0f,174.0f,166.0f,194.0f,248.0f,322.0f,403.0f,485.0f, 557.0f,611.0f,639.0f,635.0f,598.0f,527.0f,425.0f,299.0f, 153.0f,-3.0f,-155.0f,-299.0f,-429.0f,-528.0f,-602.0f,-637.0f, -638.0f,-608.0f,-549.0f,-471.0f,-374.0f,-279.0f,-185.0f,-111.0f, -52.0f,-22.0f,-25.0f,-61.0f,-123.0f,-210.0f,-316.0f,-430.0f, -550.0f,-656.0f,-756.0f,-825.0f,-874.0f,-888.0f,-873.0f,-827.0f, -756.0f,-664.0f,-561.0f,-452.0f,-344.0f,-253.0f,-174.0f,-123.0f, -101.0f,-111.0f,-145.0f,-205.0f,-286.0f,-376.0f,-469.0f,-558.0f, -631.0f,-685.0f,-707.0f,-703.0f,-664.0f,-597.0f,-506.0f,-395.0f, -276.0f,-148.0f,-30.0f,76.0f,163.0f,225.0f,260.0f,267.0f, 247.0f,207.0f,146.0f,74.0f,-5.0f,-77.0f,-145.0f,-191.0f, -218.0f,-221.0f,-196.0f,-144.0f,-69.0f,28.0f,136.0f,259.0f, 374.0f,485.0f,575.0f,646.0f,687.0f,705.0f,690.0f,648.0f, 587.0f,507.0f,422.0f,336.0f,257.0f,194.0f,150.0f,132.0f, 141.0f,175.0f,232.0f,309.0f,402.0f,500.0f,597.0f,685.0f, 758.0f,807.0f,835.0f,834.0f,808.0f,757.0f,685.0f,604.0f, 511.0f,420.0f,333.0f,260.0f,206.0f,170.0f,155.0f,168.0f, 195.0f,243.0f,302.0f,369.0f,437.0f,497.0f,547.0f,580.0f, 591.0f,580.0f,543.0f,488.0f,409.0f,315.0f,217.0f,111.0f, 10.0f,-81.0f,-151.0f,-204.0f,-232.0f,-238.0f,-220.0f,-183.0f, -132.0f,-75.0f,-12.0f,44.0f,86.0f,114.0f,121.0f,107.0f, 68.0f,10.0f,-67.0f,-156.0f,-252.0f,-352.0f,-443.0f,-524.0f, -593.0f,-642.0f,-666.0f,-671.0f,-654.0f,-617.0f,-566.0f,-505.0f, -438.0f,-374.0f,-315.0f,-269.0f,-242.0f,-233.0f,-243.0f,-277.0f, -330.0f,-398.0f,-474.0f,-558.0f,-641.0f,-714.0f,-775.0f,-819.0f, -840.0f,-841.0f,-818.0f,-778.0f,-719.0f,-649.0f,-573.0f,-500.0f, -430.0f,-375.0f,-334.0f,-312.0f,-308.0f,-322.0f,-351.0f,-393.0f, -442.0f,-493.0f,-545.0f,-584.0f,-616.0f,-631.0f,-629.0f,-608.0f, -570.0f,-517.0f,-448.0f,-370.0f,-287.0f,-204.0f,-125.0f,-57.0f, 1.0f,35.0f,54.0f,53.0f,34.0f,-1.0f,-48.0f,-102.0f, -159.0f,-213.0f,-255.0f,-285.0f,-300.0f,-293.0f,-271.0f,-228.0f, -171.0f,-102.0f,-26.0f,53.0f,128.0f,193.0f,250.0f,285.0f, 307.0f,305.0f,289.0f,250.0f,204.0f,146.0f,89.0f,36.0f, -14.0f,-45.0f,-60.0f,-58.0f,-36.0f,6.0f,63.0f,130.0f, 203.0f,277.0f,344.0f,402.0f,447.0f,470.0f,474.0f,462.0f, 432.0f,387.0f,334.0f,275.0f,218.0f,162.0f,117.0f,84.0f, 66.0f,62.0f,74.0f,101.0f,140.0f,187.0f,243.0f,292.0f, 344.0f,389.0f,421.0f,437.0f,444.0f,431.0f,401.0f,360.0f, 303.0f,241.0f,173.0f,107.0f,48.0f,1.0f,-38.0f,-55.0f, -58.0f,-44.0f,-21.0f,20.0f,62.0f,109.0f,152.0f,191.0f, 220.0f,238.0f,243.0f,234.0f,213.0f,183.0f,142.0f,97.0f, 50.0f,5.0f,-37.0f,-72.0f,-96.0f,-111.0f,-111.0f,-102.0f, -84.0f,-54.0f,-20.0f,16.0f,53.0f,86.0f,109.0f,123.0f, 130.0f,120.0f,103.0f,71.0f,29.0f,-17.0f,-67.0f,-119.0f, -170.0f,-212.0f,-246.0f,-273.0f,-284.0f,-285.0f,-268.0f,-247.0f, -212.0f,-170.0f,-125.0f,-81.0f,-43.0f,-11.0f,11.0f,21.0f, 18.0f,3.0f,-28.0f,-65.0f,-107.0f,-154.0f,-197.0f,-236.0f, -269.0f,-286.0f,-294.0f,-290.0f,-272.0f,-245.0f,-212.0f,-173.0f, -134.0f,-99.0f,-63.0f,-40.0f,-26.0f,-17.0f,-19.0f,-30.0f, -50.0f,-74.0f,-101.0f,-131.0f,-156.0f,-181.0f,-197.0f,-205.0f, -205.0f,-195.0f,-176.0f,-147.0f,-115.0f,-78.0f,-38.0f,-2.0f, 31.0f,59.0f,76.0f,88.0f,90.0f,85.0f,74.0f,61.0f, 44.0f,26.0f,13.0f,1.0f,-6.0f,-11.0f,-12.0f,-10.0f, -9.0f,-6.0f,-1.0f,0.0f,4.0f,2.0f,0.0f, 0 }; t_CKUINT glot_eee_size = 992; // data for glot_ooo.raw... SAMPLE glot_ooo_data[] = { 0.0f,-1.0f,-5.0f,-4.0f,-8.0f,-7.0f,-6.0f,-6.0f, 2.0f,8.0f,15.0f,23.0f,30.0f,38.0f,43.0f,45.0f, 46.0f,47.0f,45.0f,45.0f,44.0f,44.0f,45.0f,51.0f, 55.0f,62.0f,71.0f,76.0f,82.0f,86.0f,90.0f,88.0f, 89.0f,87.0f,86.0f,86.0f,83.0f,85.0f,86.0f,88.0f, 90.0f,96.0f,99.0f,101.0f,104.0f,106.0f,106.0f,101.0f, 99.0f,98.0f,97.0f,98.0f,96.0f,100.0f,107.0f,114.0f, 121.0f,129.0f,137.0f,142.0f,148.0f,149.0f,149.0f,144.0f, 139.0f,140.0f,138.0f,146.0f,168.0f,203.0f,256.0f,331.0f, 425.0f,544.0f,676.0f,822.0f,975.0f,1123.0f,1263.0f,1387.0f, 1491.0f,1565.0f,1616.0f,1641.0f,1648.0f,1642.0f,1621.0f,1602.0f, 1578.0f,1557.0f,1533.0f,1509.0f,1466.0f,1406.0f,1318.0f,1196.0f, 1032.0f,826.0f,573.0f,278.0f,-50.0f,-409.0f,-784.0f,-1174.0f, -1565.0f,-1951.0f,-2325.0f,-2686.0f,-3030.0f,-3358.0f,-3671.0f,-3970.0f, -4258.0f,-4533.0f,-4800.0f,-5048.0f,-5285.0f,-5501.0f,-5696.0f,-5862.0f, -5992.0f,-6081.0f,-6133.0f,-6141.0f,-6108.0f,-6027.0f,-5906.0f,-5749.0f, -5561.0f,-5342.0f,-5095.0f,-4827.0f,-4536.0f,-4233.0f,-3913.0f,-3587.0f, -3241.0f,-2885.0f,-2524.0f,-2151.0f,-1779.0f,-1392.0f,-1007.0f,-607.0f, -207.0f,208.0f,627.0f,1066.0f,1505.0f,1952.0f,2408.0f,2852.0f, 3290.0f,3703.0f,4085.0f,4430.0f,4735.0f,4991.0f,5199.0f,5358.0f, 5472.0f,5553.0f,5602.0f,5631.0f,5637.0f,5638.0f,5625.0f,5610.0f, 5588.0f,5557.0f,5510.0f,5445.0f,5364.0f,5252.0f,5117.0f,4945.0f, 4750.0f,4519.0f,4265.0f,3989.0f,3697.0f,3397.0f,3094.0f,2804.0f, 2518.0f,2254.0f,2010.0f,1789.0f,1585.0f,1400.0f,1227.0f,1066.0f, 911.0f,758.0f,607.0f,459.0f,306.0f,167.0f,33.0f,-94.0f, -209.0f,-305.0f,-393.0f,-453.0f,-500.0f,-527.0f,-534.0f,-534.0f, -508.0f,-476.0f,-433.0f,-391.0f,-339.0f,-300.0f,-260.0f,-236.0f, -220.0f,-220.0f,-241.0f,-267.0f,-314.0f,-366.0f,-430.0f,-494.0f, -567.0f,-635.0f,-698.0f,-764.0f,-822.0f,-884.0f,-941.0f,-1005.0f, -1077.0f,-1158.0f,-1254.0f,-1367.0f,-1493.0f,-1641.0f,-1798.0f,-1966.0f, -2143.0f,-2320.0f,-2490.0f,-2649.0f,-2791.0f,-2913.0f,-3014.0f,-3096.0f, -3155.0f,-3195.0f,-3223.0f,-3239.0f,-3248.0f,-3251.0f,-3249.0f,-3241.0f, -3230.0f,-3204.0f,-3171.0f,-3120.0f,-3053.0f,-2968.0f,-2858.0f,-2723.0f, -2569.0f,-2395.0f,-2206.0f,-1997.0f,-1774.0f,-1543.0f,-1305.0f,-1058.0f, -811.0f,-559.0f,-306.0f,-55.0f,197.0f,445.0f,687.0f,929.0f, 1162.0f,1381.0f,1595.0f,1799.0f,1993.0f,2175.0f,2347.0f,2508.0f, 2662.0f,2800.0f,2935.0f,3051.0f,3150.0f,3239.0f,3300.0f,3341.0f, 3353.0f,3340.0f,3298.0f,3234.0f,3147.0f,3042.0f,2920.0f,2791.0f, 2657.0f,2519.0f,2389.0f,2251.0f,2117.0f,1981.0f,1836.0f,1686.0f, 1519.0f,1339.0f,1143.0f,932.0f,706.0f,473.0f,234.0f,1.0f, -230.0f,-444.0f,-641.0f,-816.0f,-966.0f,-1095.0f,-1204.0f,-1291.0f, -1365.0f,-1431.0f,-1490.0f,-1544.0f,-1599.0f,-1651.0f,-1706.0f,-1753.0f, -1796.0f,-1832.0f,-1856.0f,-1868.0f,-1867.0f,-1849.0f,-1818.0f,-1775.0f, -1722.0f,-1662.0f,-1593.0f,-1520.0f,-1449.0f,-1372.0f,-1295.0f,-1224.0f, -1154.0f,-1087.0f,-1027.0f,-973.0f,-929.0f,-893.0f,-867.0f,-851.0f, -839.0f,-833.0f,-831.0f,-830.0f,-826.0f,-820.0f,-809.0f,-791.0f, -775.0f,-758.0f,-737.0f,-721.0f,-715.0f,-712.0f,-724.0f,-742.0f, -775.0f,-811.0f,-859.0f,-905.0f,-954.0f,-997.0f,-1033.0f,-1056.0f, -1069.0f,-1063.0f,-1043.0f,-1013.0f,-971.0f,-918.0f,-862.0f,-802.0f, -746.0f,-689.0f,-638.0f,-581.0f,-528.0f,-471.0f,-412.0f,-344.0f, -264.0f,-180.0f,-80.0f,28.0f,147.0f,269.0f,401.0f,531.0f, 663.0f,794.0f,924.0f,1051.0f,1173.0f,1289.0f,1402.0f,1509.0f, 1605.0f,1697.0f,1779.0f,1849.0f,1910.0f,1962.0f,2005.0f,2042.0f, 2072.0f,2099.0f,2122.0f,2143.0f,2158.0f,2167.0f,2170.0f,2159.0f, 2137.0f,2097.0f,2035.0f,1959.0f,1865.0f,1752.0f,1631.0f,1497.0f, 1362.0f,1226.0f,1088.0f,962.0f,834.0f,717.0f,602.0f,490.0f, 383.0f,276.0f,161.0f,47.0f,-73.0f,-199.0f,-326.0f,-457.0f, -585.0f,-711.0f,-830.0f,-943.0f,-1045.0f,-1136.0f,-1211.0f,-1273.0f, -1321.0f,-1354.0f,-1380.0f,-1391.0f,-1392.0f,-1388.0f,-1378.0f,-1363.0f, -1347.0f,-1327.0f,-1309.0f,-1288.0f,-1267.0f,-1246.0f,-1221.0f,-1188.0f, -1153.0f,-1113.0f,-1062.0f,-1006.0f,-940.0f,-870.0f,-793.0f,-711.0f, -636.0f,-555.0f,-479.0f,-410.0f,-342.0f,-282.0f,-226.0f,-181.0f, -137.0f,-102.0f,-68.0f,-43.0f,-21.0f,-3.0f,12.0f,25.0f, 36.0f,48.0f,57.0f,66.0f,74.0f,78.0f,87.0f,85.0f, 85.0f,77.0f,67.0f,54.0f,36.0f,18.0f,0.0f,-18.0f, -32.0f,-42.0f,-46.0f,-39.0f,-30.0f,-10.0f,12.0f,42.0f, 72.0f,103.0f,133.0f,162.0f,185.0f,206.0f,227.0f,243.0f, 259.0f,279.0f,301.0f,327.0f,358.0f,394.0f,433.0f,476.0f, 520.0f,570.0f,616.0f,663.0f,702.0f,740.0f,773.0f,799.0f, 818.0f,828.0f,833.0f,833.0f,825.0f,810.0f,797.0f,777.0f, 751.0f,727.0f,700.0f,672.0f,644.0f,612.0f,581.0f,546.0f, 505.0f,464.0f,416.0f,360.0f,301.0f,238.0f,167.0f,94.0f, 20.0f,-57.0f,-136.0f,-214.0f,-288.0f,-360.0f,-429.0f,-499.0f, -560.0f,-619.0f,-676.0f,-727.0f,-774.0f,-817.0f,-856.0f,-897.0f, -929.0f,-961.0f,-990.0f,-1015.0f,-1038.0f,-1057.0f,-1072.0f,-1080.0f, -1086.0f,-1083.0f,-1076.0f,-1057.0f,-1038.0f,-1011.0f,-983.0f,-949.0f, -917.0f,-883.0f,-847.0f,-816.0f,-780.0f,-748.0f,-715.0f,-678.0f, -639.0f,-600.0f,-556.0f,-513.0f,-462.0f,-415.0f,-362.0f,-314.0f, -262.0f,-213.0f,-165.0f,-118.0f,-77.0f,-31.0f,5.0f,45.0f, 76.0f,107.0f,136.0f,160.0f,181.0f,201.0f,218.0f,231.0f, 242.0f,254.0f,261.0f,268.0f,269.0f,275.0f,279.0f,277.0f, 280.0f,279.0f,276.0f,273.0f,269.0f,261.0f,250.0f,237.0f, 222.0f,205.0f,187.0f,170.0f,156.0f,144.0f,132.0f,128.0f, 130.0f,138.0f,146.0f,159.0f,176.0f,188.0f,206.0f,219.0f, 230.0f,241.0f,247.0f,251.0f,254.0f,256.0f,257.0f,257.0f, 258.0f,258.0f,260.0f,264.0f,270.0f,273.0f,280.0f,287.0f, 293.0f,300.0f,300.0f,305.0f,303.0f,298.0f,290.0f,279.0f, 262.0f,245.0f,224.0f,203.0f,181.0f,158.0f,134.0f,107.0f, 84.0f,55.0f,35.0f,6.0f,-21.0f,-50.0f,-77.0f,-111.0f, -141.0f,-176.0f,-208.0f,-244.0f,-280.0f,-313.0f,-349.0f,-384.0f, -415.0f,-448.0f,-477.0f,-503.0f,-524.0f,-543.0f,-551.0f,-562.0f, -561.0f,-563.0f,-558.0f,-551.0f,-543.0f,-531.0f,-521.0f,-509.0f, -497.0f,-483.0f,-464.0f,-446.0f,-423.0f,-397.0f,-371.0f,-339.0f, -307.0f,-270.0f,-239.0f,-200.0f,-166.0f,-134.0f,-102.0f,-69.0f, -38.0f,-10.0f,21.0f,50.0f,79.0f,112.0f,142.0f,170.0f, 198.0f,229.0f,257.0f,282.0f,305.0f,326.0f,345.0f,358.0f, 370.0f,377.0f,382.0f,385.0f,385.0f,382.0f,380.0f,371.0f, 365.0f,359.0f,349.0f,342.0f,329.0f,319.0f,304.0f,292.0f, 277.0f,262.0f,247.0f,227.0f,213.0f,194.0f,178.0f,159.0f, 143.0f,127.0f,108.0f,92.0f,73.0f,58.0f,42.0f,27.0f, 12.0f,0.0f,-8.0f,-15.0f,-21.0f,-20.0f,-22.0f,-21.0f, -16.0f,-14.0f,-11.0f,-10.0f,-13.0f,-13.0f,-20.0f,-28.0f, -37.0f,-45.0f,-53.0f,-61.0f,-64.0f,-67.0f,-64.0f,-61.0f, -54.0f,-52.0f,-46.0f,-45.0f,-45.0f,-52.0f,-63.0f,-77.0f, -92.0f,-110.0f,-128.0f,-148.0f,-163.0f,-175.0f,-191.0f,-196.0f, -203.0f,-210.0f,-216.0f,-219.0f,-225.0f,-230.0f,-240.0f,-251.0f, -258.0f,-270.0f,-282.0f,-290.0f,-303.0f,-310.0f,-321.0f,-329.0f, -338.0f,-346.0f,-354.0f,-362.0f,-369.0f,-375.0f,-379.0f,-377.0f, -374.0f,-370.0f,-358.0f,-345.0f,-328.0f,-309.0f,-289.0f,-265.0f, -242.0f,-222.0f,-198.0f,-176.0f,-154.0f,-130.0f,-110.0f,-82.0f, -58.0f,-33.0f,-4.0f,24.0f,51.0f,81.0f,107.0f,128.0f, 153.0f,176.0f,193.0f,211.0f,227.0f,239.0f,252.0f,262.0f, 276.0f,283.0f,292.0f,301.0f,304.0f,306.0f,309.0f,306.0f, 306.0f,297.0f,292.0f,284.0f,276.0f,265.0f,258.0f,252.0f, 245.0f,240.0f,230.0f,229.0f,222.0f,215.0f,204.0f,194.0f, 181.0f,166.0f,150.0f,133.0f,115.0f,94.0f,79.0f,60.0f, 44.0f,29.0f,13.0f,3.0f,-9.0f,-19.0f,-28.0f,-36.0f, -42.0f,-48.0f,-54.0f,-60.0f,-66.0f,-75.0f,-83.0f,-94.0f, -101.0f,-107.0f,-112.0f,-114.0f,-109.0f,-104.0f,-93.0f,-80.0f, -63.0f,-45.0f,-32.0f,-17.0f,-4.0f,3.0f,8.0f,9.0f, 8.0f,7.0f,3.0f,0.0f,-5.0f,-5.0f,-4.0f,-5.0f, -5.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f,0.0f, 0 }; t_CKUINT glot_ooo_size = 992; // data for glot_pop.raw... SAMPLE glot_pop_data[] = { 0.0f,0.0f,1.0f,-1.0f,0.0f,0.0f,0.0f,0.0f, 1.0f,1.0f,513.0f,561.0f,565.0f,499.0f,374.0f,188.0f, -42.0f,-306.0f,-571.0f,-821.0f,-1037.0f,-1214.0f,-1338.0f,-1422.0f, -1479.0f,-1520.0f,-1568.0f,-1628.0f,-1708.0f,-1814.0f,-1931.0f,-2062.0f, -2185.0f,-2293.0f,-2375.0f,-2432.0f,-2464.0f,-2476.0f,-2471.0f,-2458.0f, -2431.0f,-2397.0f,-2338.0f,-2247.0f,-2110.0f,-1916.0f,-1655.0f,-1330.0f, -950.0f,-528.0f,-91.0f,337.0f,730.0f,1059.0f,1310.0f,1467.0f, 1531.0f,1509.0f,1411.0f,1256.0f,1066.0f,847.0f,629.0f,415.0f, 217.0f,37.0f,-131.0f,-278.0f,-411.0f,-524.0f,-624.0f,-711.0f, -778.0f,-827.0f,-859.0f,-867.0f,-866.0f,-846.0f,-824.0f,-804.0f, -788.0f,-789.0f,-808.0f,-855.0f,-926.0f,-1019.0f,-1142.0f,-1282.0f, -1441.0f,-1617.0f,-1803.0f,-2007.0f,-2223.0f,-2446.0f,-2670.0f,-2886.0f, -3077.0f,-3235.0f,-3330.0f,-3347.0f,-3278.0f,-3107.0f,-2844.0f,-2499.0f, -2102.0f,-1674.0f,-1253.0f,-869.0f,-548.0f,-299.0f,-131.0f,-29.0f, 24.0f,59.0f,94.0f,150.0f,240.0f,368.0f,519.0f,688.0f, 856.0f,994.0f,1093.0f,1144.0f,1135.0f,1077.0f,968.0f,823.0f, 646.0f,458.0f,268.0f,82.0f,-93.0f,-255.0f,-395.0f,-523.0f, -641.0f,-749.0f,-858.0f,-979.0f,-1114.0f,-1266.0f,-1437.0f,-1610.0f, -1779.0f,-1925.0f,-2028.0f,-2073.0f,-2047.0f,-1953.0f,-1795.0f,-1592.0f, -1374.0f,-1167.0f,-995.0f,-888.0f,-851.0f,-891.0f,-983.0f,-1112.0f, -1239.0f,-1325.0f,-1345.0f,-1266.0f,-1081.0f,-788.0f,-412.0f,21.0f, 465.0f,881.0f,1223.0f,1460.0f,1576.0f,1556.0f,1423.0f,1201.0f, 934.0f,660.0f,430.0f,280.0f,234.0f,300.0f,459.0f,685.0f, 930.0f,1143.0f,1275.0f,1285.0f,1145.0f,866.0f,465.0f,-8.0f, -490.0f,-913.0f,-1208.0f,-1322.0f,-1233.0f,-941.0f,-472.0f,96.0f, 701.0f,1240.0f,1641.0f,1848.0f,1830.0f,1590.0f,1181.0f,678.0f, 174.0f,-238.0f,-481.0f,-502.0f,-293.0f,120.0f,687.0f,1322.0f, 1943.0f,2470.0f,2853.0f,3075.0f,3151.0f,3120.0f,3036.0f,2957.0f, 2929.0f,2977.0f,3082.0f,3206.0f,3299.0f,3295.0f,3153.0f,2863.0f, 2431.0f,1916.0f,1405.0f,999.0f,799.0f,891.0f,1299.0f,2024.0f, 2997.0f,4118.0f,5278.0f,6312.0f,7105.0f,7554.0f,7625.0f,7328.0f, 6724.0f,5925.0f,5063.0f,4280.0f,3700.0f,3391.0f,3411.0f,3737.0f, 4307.0f,5027.0f,5773.0f,6436.0f,6918.0f,7164.0f,7178.0f,7003.0f, 6733.0f,6509.0f,6468.0f,6734.0f,7386.0f,8444.0f,9841.0f,11430.0f, 12991.0f,14273.0f,15014.0f,14983.0f,14047.0f,12167.0f,9434.0f,6071.0f, 2379.0f,-1263.0f,-4504.0f,-7035.0f,-8657.0f,-9297.0f,-9036.0f,-8060.0f, -6653.0f,-5126.0f,-3761.0f,-2782.0f,-2285.0f,-2276.0f,-2655.0f,-3251.0f, -3867.0f,-4324.0f,-4512.0f,-4379.0f,-3970.0f,-3372.0f,-2719.0f,-2129.0f, -1704.0f,-1489.0f,-1470.0f,-1589.0f,-1747.0f,-1853.0f,-1844.0f,-1693.0f, -1423.0f,-1108.0f,-819.0f,-663.0f,-707.0f,-966.0f,-1411.0f,-1953.0f, -2478.0f,-2836.0f,-2913.0f,-2625.0f,-1947.0f,-922.0f,362.0f,1760.0f, 3116.0f,4278.0f,5127.0f,5586.0f,5646.0f,5340.0f,4750.0f,3974.0f, 3115.0f,2269.0f,1495.0f,822.0f,254.0f,-237.0f,-678.0f,-1090.0f, -1487.0f,-1856.0f,-2172.0f,-2406.0f,-2515.0f,-2473.0f,-2289.0f,-1978.0f, -1593.0f,-1201.0f,-876.0f,-681.0f,-661.0f,-836.0f,-1184.0f,-1664.0f, -2198.0f,-2717.0f,-3148.0f,-3432.0f,-3544.0f,-3495.0f,-3322.0f,-3073.0f, -2829.0f,-2648.0f,-2581.0f,-2666.0f,-2885.0f,-3213.0f,-3593.0f,-3957.0f, -4233.0f,-4365.0f,-4312.0f,-4064.0f,-3636.0f,-3057.0f,-2378.0f,-1656.0f, -945.0f,-289.0f,262.0f,697.0f,1002.0f,1167.0f,1205.0f,1115.0f, 917.0f,630.0f,272.0f,-130.0f,-548.0f,-946.0f,-1294.0f,-1572.0f, -1753.0f,-1837.0f,-1835.0f,-1763.0f,-1642.0f,-1510.0f,-1391.0f,-1303.0f, -1259.0f,-1251.0f,-1264.0f,-1281.0f,-1271.0f,-1229.0f,-1139.0f,-1000.0f, -835.0f,-669.0f,-530.0f,-446.0f,-440.0f,-517.0f,-678.0f,-905.0f, -1181.0f,-1471.0f,-1750.0f,-1999.0f,-2197.0f,-2333.0f,-2411.0f,-2422.0f, -2375.0f,-2259.0f,-2090.0f,-1850.0f,-1543.0f,-1169.0f,-737.0f,-260.0f, 232.0f,707.0f,1122.0f,1444.0f,1639.0f,1688.0f,1586.0f,1347.0f, 1010.0f,615.0f,212.0f,-153.0f,-440.0f,-635.0f,-733.0f,-759.0f, -745.0f,-744.0f,-793.0f,-930.0f,-1170.0f,-1513.0f,-1938.0f,-2401.0f, -2860.0f,-3257.0f,-3553.0f,-3720.0f,-3747.0f,-3643.0f,-3430.0f,-3141.0f, -2811.0f,-2480.0f,-2170.0f,-1903.0f,-1676.0f,-1497.0f,-1356.0f,-1241.0f, -1151.0f,-1083.0f,-1041.0f,-1016.0f,-1017.0f,-1041.0f,-1081.0f,-1127.0f, -1165.0f,-1182.0f,-1164.0f,-1110.0f,-1007.0f,-871.0f,-706.0f,-533.0f, -361.0f,-211.0f,-89.0f,-4.0f,51.0f,68.0f,63.0f,48.0f, 24.0f,5.0f,-12.0f,-22.0f,-26.0f,-23.0f,-17.0f,-10.0f, -5.0f,2.0f,4.0f,6.0f,6.0f,6.0f,5.0f,0.0f, 0.0f, 0 }; t_CKUINT glot_pop_size = 521; chuck-1.2.0.8.dfsg/src/util_raw.h0000644000175000017500000000610110600421720015121 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // file: util_raw.h // desc: raw waves from STK // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Spring 2004 //----------------------------------------------------------------------------- #ifndef __UTIL_RAW_H__ #define __UTIL_RAW_H__ #include "chuck_def.h" #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif // begin the abuse of memory extern SAMPLE ahh_data[]; extern SAMPLE britestk_data[]; extern SAMPLE dope_data[]; extern SAMPLE eee_data[]; extern SAMPLE fwavblnk_data[]; extern SAMPLE halfwave_data[]; extern SAMPLE impuls10_data[]; extern SAMPLE impuls20_data[]; extern SAMPLE impuls40_data[]; extern SAMPLE mand1_data[]; extern SAMPLE mandpluk_data[]; extern SAMPLE marmstk1_data[]; extern SAMPLE ooo_data[]; extern SAMPLE peksblnk_data[]; extern SAMPLE ppksblnk_data[]; extern SAMPLE silence_data[]; extern SAMPLE sineblnk_data[]; extern SAMPLE sinewave_data[]; extern SAMPLE snglpeak_data[]; extern SAMPLE twopeaks_data[]; extern SAMPLE glot_ahh_data[]; extern SAMPLE glot_eee_data[]; extern SAMPLE glot_ooo_data[]; extern SAMPLE glot_pop_data[]; extern t_CKUINT ahh_size; extern t_CKUINT britestk_size; extern t_CKUINT dope_size; extern t_CKUINT eee_size; extern t_CKUINT fwavblnk_size; extern t_CKUINT halfwave_size; extern t_CKUINT impuls10_size; extern t_CKUINT impuls20_size; extern t_CKUINT impuls40_size; extern t_CKUINT mand1_size; extern t_CKUINT mandpluk_size; extern t_CKUINT marmstk1_size; extern t_CKUINT ooo_size; extern t_CKUINT peksblnk_size; extern t_CKUINT ppksblnk_size; extern t_CKUINT silence_size; extern t_CKUINT sineblnk_size; extern t_CKUINT sinewave_size; extern t_CKUINT snglpeak_size; extern t_CKUINT twopeaks_size; extern t_CKUINT glot_ahh_size; extern t_CKUINT glot_eee_size; extern t_CKUINT glot_ooo_size; extern t_CKUINT glot_pop_size; #if defined(_cplusplus) || defined(__cplusplus) } #endif #endif chuck-1.2.0.8.dfsg/src/util_sndfile.c0000644000175000017500000363617210600421720015773 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ /* ** libsndfile Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //----------------------------------------------------------------------------- // name: util_sndfile.c // desc: libsndfile for ChucK // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ari Lazier (alazier@alumni.princeton.edu) // libsndfile: Erik de Castro Lopo (erikd@mega-nerd.com) //----------------------------------------------------------------------------- #include "util_sndfile.h" #include "chuck_def.h" #include /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* * See private.h for the more commonly used macro versions. */ #include #include #define saturate(x) \ ((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x)) word gsm_add ( word a, word b) { longword sum = (longword)a + (longword)b; return saturate(sum); } word gsm_sub ( word a, word b) { longword diff = (longword)a - (longword)b; return saturate(diff); } word gsm_mult ( word a, word b) { if (a == MIN_WORD && b == MIN_WORD) return MAX_WORD; return SASR_L( (longword)a * (longword)b, 15 ); } word gsm_mult_r ( word a, word b) { if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD; else { longword prod = (longword)a * (longword)b + 16384; prod >>= 15; return prod & 0xFFFF; } } word gsm_abs (word a) { return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a; } longword gsm_L_mult (word a, word b) { assert( a != MIN_WORD || b != MIN_WORD ); return ((longword)a * (longword)b) << 1; } longword gsm_L_add ( longword a, longword b) { if (a < 0) { if (b >= 0) return a + b; else { ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1); return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2; } } else if (b <= 0) return a + b; else { ulongword A = (ulongword)a + (ulongword)b; return A > MAX_LONGWORD ? MAX_LONGWORD : A; } } longword gsm_L_sub ( longword a, longword b) { if (a >= 0) { if (b >= 0) return a - b; else { /* a>=0, b<0 */ ulongword A = (ulongword)a + -(b + 1); return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1); } } else if (b <= 0) return a - b; else { /* a<0, b>0 */ ulongword A = (ulongword)-(a + 1) + b; return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1; } } static unsigned char const bitoff[ 256 ] = { 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; word gsm_norm (longword a ) /* * the number of left shifts needed to normalize the 32 bit * variable L_var1 for positive values on the interval * * with minimum of * minimum of 1073741824 (01000000000000000000000000000000) and * maximum of 2147483647 (01111111111111111111111111111111) * * * and for negative values on the interval with * minimum of -2147483648 (-10000000000000000000000000000000) and * maximum of -1073741824 ( -1000000000000000000000000000000). * * in order to normalize the result, the following * operation must be done: L_norm_var1 = L_var1 << norm( L_var1 ); * * (That's 'ffs', only from the left, not the right..) */ { assert(a != 0); if (a < 0) { if (a <= -1073741824) return 0; a = ~a; } return a & 0xffff0000 ? ( a & 0xff000000 ? -1 + bitoff[ 0xFF & (a >> 24) ] : 7 + bitoff[ 0xFF & (a >> 16) ] ) : ( a & 0xff00 ? 15 + bitoff[ 0xFF & (a >> 8) ] : 23 + bitoff[ 0xFF & a ] ); } longword gsm_L_asl (longword a, int n) { if (n >= 32) return 0; if (n <= -32) return -(a < 0); if (n < 0) return gsm_L_asr(a, -n); return a << n; } word gsm_asr (word a, int n) { if (n >= 16) return -(a < 0); if (n <= -16) return 0; if (n < 0) return a << -n; return SASR_W (a, (word) n); } word gsm_asl (word a, int n) { if (n >= 16) return 0; if (n <= -16) return -(a < 0); if (n < 0) return gsm_asr(a, -n); return a << n; } longword gsm_L_asr (longword a, int n) { if (n >= 32) return -(a < 0); if (n <= -32) return 0; if (n < 0) return a << -n; return SASR_L (a, (word) n); } /* ** word gsm_asr (word a, int n) ** { ** if (n >= 16) return -(a < 0); ** if (n <= -16) return 0; ** if (n < 0) return a << -n; ** ** # ifdef SASR_W ** return a >> n; ** # else ** if (a >= 0) return a >> n; ** else return -(word)( -(uword)a >> n ); ** # endif ** } ** */ /* * (From p. 46, end of section 4.2.5) * * NOTE: The following lines gives [sic] one correct implementation * of the div(num, denum) arithmetic operation. Compute div * which is the integer division of num by denum: with denum * >= num > 0 */ word gsm_div (word num, word denum) { longword L_num = num; longword L_denum = denum; word div = 0; int k = 15; /* The parameter num sometimes becomes zero. * Although this is explicitly guarded against in 4.2.5, * we assume that the result should then be zero as well. */ /* assert(num != 0); */ assert(num >= 0 && denum >= num); if (num == 0) return 0; while (k--) { div <<= 1; L_num <<= 1; if (L_num >= L_denum) { L_num -= L_denum; div++; } } return div; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M')) #define AIFF_MARKER (MAKE_MARKER ('A', 'I', 'F', 'F')) #define AIFC_MARKER (MAKE_MARKER ('A', 'I', 'F', 'C')) #define COMM_MARKER (MAKE_MARKER ('C', 'O', 'M', 'M')) #define SSND_MARKER (MAKE_MARKER ('S', 'S', 'N', 'D')) #define MARK_MARKER (MAKE_MARKER ('M', 'A', 'R', 'K')) #define INST_MARKER (MAKE_MARKER ('I', 'N', 'S', 'T')) #define APPL_MARKER (MAKE_MARKER ('A', 'P', 'P', 'L')) #define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' ')) #define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E')) #define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H')) #define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O')) #define COMT_MARKER (MAKE_MARKER ('C', 'O', 'M', 'T')) #define FVER_MARKER (MAKE_MARKER ('F', 'V', 'E', 'R')) #define SFX_MARKER (MAKE_MARKER ('S', 'F', 'X', '!')) #define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) /* Supported AIFC encodings.*/ #define NONE_MARKER (MAKE_MARKER ('N', 'O', 'N', 'E')) #define sowt_MARKER (MAKE_MARKER ('s', 'o', 'w', 't')) #define twos_MARKER (MAKE_MARKER ('t', 'w', 'o', 's')) #define raw_MARKER (MAKE_MARKER ('r', 'a', 'w', ' ')) #define in32_MARKER (MAKE_MARKER ('i', 'n', '3', '2')) #define ni32_MARKER (MAKE_MARKER ('2', '3', 'n', 'i')) #define fl32_MARKER (MAKE_MARKER ('f', 'l', '3', '2')) #define FL32_MARKER (MAKE_MARKER ('F', 'L', '3', '2')) #define fl64_MARKER (MAKE_MARKER ('f', 'l', '6', '4')) #define FL64_MARKER (MAKE_MARKER ('F', 'L', '6', '4')) #define ulaw_MARKER (MAKE_MARKER ('u', 'l', 'a', 'w')) #define ULAW_MARKER (MAKE_MARKER ('U', 'L', 'A', 'W')) #define alaw_MARKER (MAKE_MARKER ('a', 'l', 'a', 'w')) #define ALAW_MARKER (MAKE_MARKER ('A', 'L', 'A', 'W')) #define DWVW_MARKER (MAKE_MARKER ('D', 'W', 'V', 'W')) #define GSM_MARKER (MAKE_MARKER ('G', 'S', 'M', ' ')) #define ima4_MARKER (MAKE_MARKER ('i', 'm', 'a', '4')) /* Unsupported AIFC encodings.*/ #define MAC3_MARKER (MAKE_MARKER ('M', 'A', 'C', '3')) #define MAC6_MARKER (MAKE_MARKER ('M', 'A', 'C', '6')) #define ADP4_MARKER (MAKE_MARKER ('A', 'D', 'P', '4')) /* Predfined chunk sizes. */ #define SIZEOF_AIFF_COMM 18 #define SIZEOF_AIFC_COMM_MIN 22 #define SIZEOF_AIFC_COMM 24 #define SIZEOF_SSND_CHUNK 8 #define SIZEOF_INST_CHUNK 20 /* AIFC/IMA4 defines. */ #define AIFC_IMA4_BLOCK_LEN 34 #define AIFC_IMA4_SAMPLES_PER_BLOCK 64 /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ enum { aiffHAVE_FORM = 0x01, HAVE_AIFF = 0x02, HAVE_COMM = 0x04, HAVE_SSND = 0x08 } ; typedef struct { unsigned int size ; short numChannels ; unsigned int numSampleFrames ; short sampleSize ; unsigned char sampleRate [10] ; unsigned int encoding ; char zero_bytes [2] ; } COMM_CHUNK ; typedef struct { unsigned int offset ; unsigned int blocksize ; } SSND_CHUNK ; typedef struct { short playMode ; unsigned short beginLoop ; unsigned short endLoop ; } INST_LOOP ; typedef struct { char baseNote ; /* all notes are MIDI note numbers */ char detune ; /* cents off, only -50 to +50 are significant */ char lowNote ; char highNote ; char lowVelocity ; /* 1 to 127 */ char highVelocity ; /* 1 to 127 */ short gain ; /* in dB, 0 is normal */ INST_LOOP sustain_loop ; INST_LOOP release_loop ; } INST_CHUNK ; /*------------------------------------------------------------------------------ * Private static functions. */ static int aiff_close (SF_PRIVATE *psf) ; static int tenbytefloat2int (unsigned char *bytes) ; static void uint2tenbytefloat (unsigned int num, unsigned char *bytes) ; static int aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) ; static int aiff_write_header (SF_PRIVATE *psf, int calc_length) ; static int aiff_write_tailer (SF_PRIVATE *psf) ; static void aiff_write_strings (SF_PRIVATE *psf, int location) ; static int aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static const char *get_loop_mode_str (short mode) ; /*------------------------------------------------------------------------------ ** Public function. */ int aiff_open (SF_PRIVATE *psf) { COMM_CHUNK comm_fmt ; int error, subformat ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = aiff_read_header (psf, &comm_fmt))) return error ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AIFF) return SFE_BAD_OPEN_FORMAT ; if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) { psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; psf->has_peak = SF_TRUE ; psf->peak_loc = SF_PEAK_START ; } ; if (psf->mode != SFM_RDWR || psf->filelength < 40) { psf->filelength = 0 ; psf->datalength = 0 ; psf->dataoffset = 0 ; psf->sf.frames = 0 ; } ; psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; if ((error = aiff_write_header (psf, SF_FALSE))) return error ; psf->write_header = aiff_write_header ; } ; psf->close = aiff_close ; psf->command = aiff_command ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_U8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_S8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; /* Lite remove start */ case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; case SF_FORMAT_DWVW_12 : error = dwvw_init (psf, 12) ; break ; case SF_FORMAT_DWVW_16 : error = dwvw_init (psf, 16) ; break ; case SF_FORMAT_DWVW_24 : error = dwvw_init (psf, 24) ; break ; case SF_FORMAT_DWVW_N : if (psf->mode != SFM_READ) { error = SFE_DWVW_BAD_BITWIDTH ; break ; } ; if (comm_fmt.sampleSize >= 8 && comm_fmt.sampleSize < 24) { error = dwvw_init (psf, comm_fmt.sampleSize) ; psf->sf.frames = comm_fmt.numSampleFrames ; break ; } ; psf_log_printf (psf, "AIFC/DWVW : Bad bitwidth %d\n", comm_fmt.sampleSize) ; error = SFE_DWVW_BAD_BITWIDTH ; break ; case SF_FORMAT_IMA_ADPCM : /* ** IMA ADPCM encoded AIFF files always have a block length ** of 34 which decodes to 64 samples. */ error = aiff_ima_init (psf, AIFC_IMA4_BLOCK_LEN, AIFC_IMA4_SAMPLES_PER_BLOCK) ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : error = gsm610_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; if (psf->mode == SFM_READ) psf->blockwidth = psf->sf.channels * psf->bytewidth ; return error ; } /* aiff_open */ /*========================================================================================== ** Private functions. */ static int aiff_read_header (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) { SSND_CHUNK ssnd_fmt ; int marker, dword, bytesread, k ; int FORMsize, SSNDsize ; int filetype, found_chunk = 0, done = 0, error = 0 ; char *cptr, byte ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "p", 0) ; memset (comm_fmt, 0, sizeof (COMM_CHUNK)) ; /* Until recently AIF* file were all BIG endian. */ psf->endian = SF_ENDIAN_BIG ; /* AIFF files can apparently have their chunks in any order. However, they ** must have a FORM chunk. Approach here is to read all the chunks one by ** one and then check for the mandatory chunks at the end. */ while (! done) { psf_binheader_readf (psf, "m", &marker) ; if (psf->mode == SFM_RDWR && (found_chunk & HAVE_SSND)) return SFE_AIFF_RW_SSND_NOT_LAST ; switch (marker) { case FORM_MARKER : if (found_chunk) return SFE_AIFF_NO_FORM ; psf_binheader_readf (psf, "E4", &FORMsize) ; if (psf->fileoffset > 0 && psf->filelength > FORMsize + 8) { /* Set file length. */ psf->filelength = FORMsize + 8 ; psf_log_printf (psf, "FORM : %u\n", FORMsize) ; } else if (FORMsize != psf->filelength - 2 * SIGNED_SIZEOF (dword)) { dword = psf->filelength - 2 * sizeof (dword) ; psf_log_printf (psf, "FORM : %u (should be %u)\n", FORMsize, dword) ; FORMsize = dword ; } else psf_log_printf (psf, "FORM : %u\n", FORMsize) ; found_chunk |= aiffHAVE_FORM ; break ; case AIFC_MARKER : case AIFF_MARKER : if (! (found_chunk & aiffHAVE_FORM)) return SFE_AIFF_AIFF_NO_FORM ; filetype = marker ; psf_log_printf (psf, " %M\n", marker) ; found_chunk |= HAVE_AIFF ; break ; case COMM_MARKER : error = aiff_read_comm_chunk (psf, comm_fmt) ; psf->sf.samplerate = tenbytefloat2int (comm_fmt->sampleRate) ; psf->sf.frames = comm_fmt->numSampleFrames ; psf->sf.channels = comm_fmt->numChannels ; psf->bytewidth = BITWIDTH2BYTES (comm_fmt->sampleSize) ; if (error) return error ; found_chunk |= HAVE_COMM ; break ; case PEAK_MARKER : /* Must have COMM chunk before PEAK chunk. */ if ((found_chunk & (aiffHAVE_FORM | HAVE_AIFF | HAVE_COMM)) != (aiffHAVE_FORM | HAVE_AIFF | HAVE_COMM)) return SFE_AIFF_PEAK_B4_COMM ; psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, "%M : %d\n", marker, dword) ; if (dword != SIGNED_SIZEOF (PEAK_CHUNK) + psf->sf.channels * SIGNED_SIZEOF (PEAK_POS)) { psf_binheader_readf (psf, "j", dword) ; psf_log_printf (psf, "*** File PEAK chunk bigger than sizeof (PEAK_CHUNK).\n") ; return SFE_WAV_BAD_PEAK ; } ; psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; /* read in rest of PEAK chunk. */ psf_binheader_readf (psf, "E44", &(psf->pchunk->version), &(psf->pchunk->timestamp)) ; if (psf->pchunk->version != 1) psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->pchunk->version) ; else psf_log_printf (psf, " version : %d\n", psf->pchunk->version) ; psf_log_printf (psf, " time stamp : %d\n", psf->pchunk->timestamp) ; psf_log_printf (psf, " Ch Position Value\n") ; cptr = (char *) psf->buffer ; for (dword = 0 ; dword < psf->sf.channels ; dword++) { psf_binheader_readf (psf, "Ef4", &(psf->pchunk->peaks [dword].value), &(psf->pchunk->peaks [dword].position)) ; LSF_SNPRINTF (cptr, sizeof (psf->buffer), " %2d %-12d %g\n", dword, psf->pchunk->peaks [dword].position, psf->pchunk->peaks [dword].value) ; cptr [sizeof (psf->buffer) - 1] = 0 ; psf_log_printf (psf, cptr) ; } ; psf->has_peak = SF_TRUE ; /* Found PEAK chunk. */ break ; case SSND_MARKER : psf_binheader_readf (psf, "E444", &SSNDsize, &(ssnd_fmt.offset), &(ssnd_fmt.blocksize)) ; psf->datalength = SSNDsize - sizeof (ssnd_fmt) ; psf->dataoffset = psf_ftell (psf) ; if (psf->datalength > psf->filelength - psf->dataoffset || psf->datalength < 0) { psf_log_printf (psf, " SSND : %u (should be %D)\n", SSNDsize, psf->filelength - psf->dataoffset + sizeof (SSND_CHUNK)) ; psf->datalength = psf->filelength - psf->dataoffset ; } else psf_log_printf (psf, " SSND : %u\n", SSNDsize) ; /* Only set dataend if there really is data at the end. */ if (psf->datalength + psf->dataoffset < psf->filelength) psf->dataend = psf->datalength + psf->dataoffset ; psf_log_printf (psf, " Offset : %u\n", ssnd_fmt.offset) ; psf_log_printf (psf, " Block Size : %u\n", ssnd_fmt.blocksize) ; found_chunk |= HAVE_SSND ; if (! psf->sf.seekable) break ; /* Seek to end of SSND chunk. */ psf_fseek (psf, psf->dataoffset + psf->datalength + (SSNDsize & 1), SEEK_SET) ; break ; case c_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; psf_store_string (psf, SF_STR_COPYRIGHT, cptr) ; break ; case AUTH_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; psf_store_string (psf, SF_STR_ARTIST, cptr) ; break ; case COMT_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; psf_store_string (psf, SF_STR_COMMENT, cptr) ; break ; case APPL_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword >= SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big, skipping)\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; for (k = 0 ; k < dword ; k++) if (! isprint (cptr [k])) { cptr [k] = 0 ; break ; } ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; psf_store_string (psf, SF_STR_SOFTWARE, cptr) ; break ; case NAME_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; psf_store_string (psf, SF_STR_TITLE, cptr) ; break ; case ANNO_MARKER : psf_binheader_readf (psf, "E4", &dword) ; dword += (dword & 1) ; if (dword == 0) break ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " %M : %d (too big)\n", marker, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", marker, cptr) ; break ; case INST_MARKER : psf_binheader_readf (psf, "E4", &dword) ; if (dword != SIZEOF_INST_CHUNK) { psf_log_printf (psf, " %M : %d (should be %d)\n", marker, dword, SIZEOF_INST_CHUNK) ; psf_binheader_readf (psf, "j", dword) ; break ; } ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; { unsigned char bytes [6] ; short gain ; psf_binheader_readf (psf, "b", bytes, 6) ; psf_log_printf (psf, " Base Note : %u\n Detune : %u\n" " Low Note : %u\n High Note : %u\n" " Low Vel. : %u\n High Vel. : %u\n", bytes [0], bytes [1], bytes [2], bytes [3], bytes [4], bytes [5]) ; psf_binheader_readf (psf, "E2", &gain) ; psf_log_printf (psf, " Gain (dB) : %d\n", gain) ; } ; { short mode ; /* 0 - no loop, 1 - forward looping, 2 - backward looping */ const char *loop_mode ; unsigned short begin, end ; psf_binheader_readf (psf, "E222", &mode, &begin, &end) ; loop_mode = get_loop_mode_str (mode) ; psf_log_printf (psf, " Sustain\n mode : %d => %s\n begin : %u\n end : %u\n", mode, loop_mode, begin, end) ; psf_binheader_readf (psf, "E222", &mode, &begin, &end) ; loop_mode = get_loop_mode_str (mode) ; psf_log_printf (psf, " Release\n mode : %d => %s\n begin : %u\n end : %u\n", mode, loop_mode, begin, end) ; } ; break ; case MARK_MARKER : psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; { unsigned short mark_count, mark_id ; unsigned char pstr_len ; unsigned int position ; bytesread = psf_binheader_readf (psf, "E2", &mark_count) ; psf_log_printf (psf, " Count : %d\n", mark_count) ; while (mark_count && bytesread < dword) { bytesread += psf_binheader_readf (psf, "E241", &mark_id, &position, &pstr_len) ; psf_log_printf (psf, " Mark ID : %u\n Position : %u\n", mark_id, position) ; pstr_len += (pstr_len & 1) + 1 ; /* fudgy, fudgy, hack, hack */ bytesread += psf_binheader_readf (psf, "b", psf->buffer, pstr_len) ; psf_log_printf (psf, " Name : %s\n", psf->buffer) ; mark_count -- ; } ; } ; psf_binheader_readf (psf, "j", dword - bytesread) ; break ; case FVER_MARKER : case SFX_MARKER : psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; case NONE_MARKER : /* Fix for broken AIFC files with incorrect COMM chunk length. */ psf_binheader_readf (psf, "1", &byte) ; dword = byte ; psf_binheader_readf (psf, "j", dword) ; break ; default : if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) { psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; } ; if ((dword = psf_ftell (psf)) & 0x03) { psf_log_printf (psf, " Unknown chunk marker %X at position %d. Resyncing.\n", marker, dword - 4) ; psf_binheader_readf (psf, "j", -3) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker %X at position %D. Exiting parser.\n", marker, psf_ftell (psf)) ; done = 1 ; break ; } ; /* switch (marker) */ if ((! psf->sf.seekable) && (found_chunk & HAVE_SSND)) break ; if (psf_ftell (psf) >= psf->filelength - (2 * SIGNED_SIZEOF (dword))) break ; if (psf->logindex >= SIGNED_SIZEOF (psf->logbuffer) - 2) return SFE_LOG_OVERRUN ; } ; /* while (1) */ if (! (found_chunk & aiffHAVE_FORM)) return SFE_AIFF_NO_FORM ; if (! (found_chunk & HAVE_AIFF)) return SFE_AIFF_COMM_NO_FORM ; if (! (found_chunk & HAVE_COMM)) return SFE_AIFF_SSND_NO_COMM ; if (! psf->dataoffset) return SFE_AIFF_NO_DATA ; return 0 ; } /* aiff_read_header */ static int aiff_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { aiff_write_tailer (psf) ; aiff_write_header (psf, SF_TRUE) ; } ; return 0 ; } /* aiff_close */ static int aiff_read_comm_chunk (SF_PRIVATE *psf, COMM_CHUNK *comm_fmt) { int error = 0, bytesread, subformat ; bytesread = psf_binheader_readf (psf, "E4", &(comm_fmt->size)) ; /* The COMM chunk has an int aligned to an odd word boundary. Some ** procesors are not able to deal with this (ie bus fault) so we have ** to take special care. */ comm_fmt->size += comm_fmt->size & 1 ; bytesread += psf_binheader_readf (psf, "E242b", &(comm_fmt->numChannels), &(comm_fmt->numSampleFrames), &(comm_fmt->sampleSize), &(comm_fmt->sampleRate), SIGNED_SIZEOF (comm_fmt->sampleRate)) ; if (comm_fmt->size == SIZEOF_AIFF_COMM) comm_fmt->encoding = NONE_MARKER ; else if (comm_fmt->size == SIZEOF_AIFC_COMM_MIN) bytesread += psf_binheader_readf (psf, "Em", &(comm_fmt->encoding)) ; else if (comm_fmt->size >= SIZEOF_AIFC_COMM) { unsigned char encoding_len ; bytesread += psf_binheader_readf (psf, "Em1", &(comm_fmt->encoding), &encoding_len) ; memset (psf->buffer, 0, comm_fmt->size) ; bytesread += psf_binheader_readf (psf, "b", psf->buffer, comm_fmt->size - SIZEOF_AIFC_COMM + 1) ; psf->buffer [encoding_len] = 0 ; } ; psf_log_printf (psf, " COMM : %d\n", comm_fmt->size) ; psf_log_printf (psf, " Sample Rate : %d\n", tenbytefloat2int (comm_fmt->sampleRate)) ; psf_log_printf (psf, " Frames : %u%s\n", comm_fmt->numSampleFrames, (comm_fmt->numSampleFrames == 0 && psf->filelength > 100) ? " (Should not be 0)" : "") ; psf_log_printf (psf, " Channels : %d\n", comm_fmt->numChannels) ; /* Found some broken 'fl32' files with comm.samplesize == 16. Fix it here. */ if ((comm_fmt->encoding == fl32_MARKER || comm_fmt->encoding == FL32_MARKER) && comm_fmt->sampleSize != 32) { psf_log_printf (psf, " Sample Size : %d (should be 32)\n", comm_fmt->sampleSize) ; comm_fmt->sampleSize = 32 ; } else if ((comm_fmt->encoding == fl64_MARKER || comm_fmt->encoding == FL64_MARKER) && comm_fmt->sampleSize != 64) { psf_log_printf (psf, " Sample Size : %d (should be 64)\n", comm_fmt->sampleSize) ; comm_fmt->sampleSize = 64 ; } else psf_log_printf (psf, " Sample Size : %d\n", comm_fmt->sampleSize) ; subformat = s_bitwidth_to_subformat (comm_fmt->sampleSize) ; psf->endian = SF_ENDIAN_BIG ; switch (comm_fmt->encoding) { case NONE_MARKER : psf->sf.format = (SF_FORMAT_AIFF | subformat) ; break ; case twos_MARKER : case in32_MARKER : psf->sf.format = (SF_ENDIAN_BIG | SF_FORMAT_AIFF | subformat) ; break ; case sowt_MARKER : case ni32_MARKER : psf->endian = SF_ENDIAN_LITTLE ; psf->sf.format = (SF_ENDIAN_LITTLE | SF_FORMAT_AIFF | subformat) ; break ; case fl32_MARKER : case FL32_MARKER : psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ; break ; case ulaw_MARKER : case ULAW_MARKER : psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_ULAW) ; break ; case alaw_MARKER : case ALAW_MARKER : psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_ALAW) ; break ; case fl64_MARKER : case FL64_MARKER : psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_DOUBLE) ; break ; case raw_MARKER : psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_PCM_U8) ; break ; case DWVW_MARKER : psf->sf.format = SF_FORMAT_AIFF ; switch (comm_fmt->sampleSize) { case 12 : psf->sf.format |= SF_FORMAT_DWVW_12 ; break ; case 16 : psf->sf.format |= SF_FORMAT_DWVW_16 ; break ; case 24 : psf->sf.format |= SF_FORMAT_DWVW_24 ; break ; default : psf->sf.format |= SF_FORMAT_DWVW_N ; break ; } ; break ; case GSM_MARKER : psf->sf.format = SF_FORMAT_AIFF ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_GSM610) ; break ; case ima4_MARKER : psf->endian = SF_ENDIAN_BIG ; psf->sf.format = (SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM) ; break ; default : psf_log_printf (psf, "AIFC : Unimplemented format : %M\n", comm_fmt->encoding) ; error = SFE_UNIMPLEMENTED ; } ; if (! psf->buffer [0]) psf_log_printf (psf, " Encoding : %M\n", comm_fmt->encoding) ; else psf_log_printf (psf, " Encoding : %M => %s\n", comm_fmt->encoding, (char*) psf->buffer) ; return error ; } /* aiff_read_comm_chunk */ static int aiff_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; unsigned char comm_sample_rate [10], comm_zero_bytes [2] = { 0, 0 } ; unsigned int comm_type, comm_size, comm_encoding, comm_frames ; int k, endian ; short bit_width ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; if (psf->mode == SFM_RDWR && psf->dataoffset > 0) { /* Assuming here that the header has already been written and just ** needs to be corrected for new data length. That means that we ** only change the length fields of the FORM and SSND chunks; ** everything else can be skipped over. */ /* First write new FORM chunk. */ psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; /* Now write frame count field of COMM chunk header. */ psf->headindex = 0 ; psf_fseek (psf, 22, SEEK_SET) ; psf_binheader_writef (psf, "Et8", psf->sf.frames) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; /* Now write new SSND chunk header. */ psf->headindex = 0 ; psf_fseek (psf, psf->dataoffset - 16, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return 0 ; } ; endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && endian == SF_ENDIAN_CPU) endian = SF_ENDIAN_LITTLE ; /* Standard value here. */ bit_width = psf->bytewidth * 8 ; comm_frames = (psf->sf.frames > 0xFFFFFFFF) ? 0xFFFFFFFF : psf->sf.frames ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : switch (endian) { case SF_ENDIAN_BIG : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = twos_MARKER ; break ; case SF_ENDIAN_LITTLE : psf->endian = SF_ENDIAN_LITTLE ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = sowt_MARKER ; break ; default : /* SF_ENDIAN_FILE */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFF_MARKER ; comm_size = SIZEOF_AIFF_COMM ; comm_encoding = 0 ; break ; } ; break ; case SF_FORMAT_FLOAT : /* Big endian floating point. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = FL32_MARKER ; /* Use 'FL32' because its easier to read. */ break ; case SF_FORMAT_DOUBLE : /* Big endian double precision floating point. */ psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = FL64_MARKER ; /* Use 'FL64' because its easier to read. */ break ; case SF_FORMAT_ULAW : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = ulaw_MARKER ; break ; case SF_FORMAT_ALAW : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = alaw_MARKER ; break ; case SF_FORMAT_PCM_U8 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = raw_MARKER ; break ; case SF_FORMAT_DWVW_12 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 12 ; break ; case SF_FORMAT_DWVW_16 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 16 ; break ; case SF_FORMAT_DWVW_24 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = DWVW_MARKER ; /* Override standard value here.*/ bit_width = 24 ; break ; case SF_FORMAT_GSM610 : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = GSM_MARKER ; /* Override standard value here.*/ bit_width = 16 ; break ; case SF_FORMAT_IMA_ADPCM : psf->endian = SF_ENDIAN_BIG ; comm_type = AIFC_MARKER ; comm_size = SIZEOF_AIFC_COMM ; comm_encoding = ima4_MARKER ; /* Override standard value here.*/ bit_width = 16 ; comm_frames = psf->sf.frames / AIFC_IMA4_SAMPLES_PER_BLOCK ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "Etm8", FORM_MARKER, psf->filelength - 8) ; /* Write COMM chunk. */ psf_binheader_writef (psf, "Emm4", comm_type, COMM_MARKER, comm_size) ; uint2tenbytefloat (psf->sf.samplerate, comm_sample_rate) ; psf_binheader_writef (psf, "Et242", psf->sf.channels, comm_frames, bit_width) ; psf_binheader_writef (psf, "b", comm_sample_rate, sizeof (comm_sample_rate)) ; /* AIFC chunks have some extra data. */ if (comm_type == AIFC_MARKER) psf_binheader_writef (psf, "mb", comm_encoding, comm_zero_bytes, sizeof (comm_zero_bytes)) ; if (psf->str_flags & SF_STR_LOCATE_START) aiff_write_strings (psf, SF_STR_LOCATE_START) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_START) { psf_binheader_writef (psf, "Em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "E44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "Ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; /* XXXXX */ } ; /* Write SSND chunk. */ psf_binheader_writef (psf, "Etm844", SSND_MARKER, psf->datalength + SIZEOF_SSND_CHUNK, 0, 0) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* aiff_write_header */ static int aiff_write_tailer (SF_PRIVATE *psf) { int k ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf->dataend = psf_fseek (psf, 0, SEEK_END) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_END) { psf_binheader_writef (psf, "Em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "E44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "Ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; /* XXXXX */ } ; if (psf->str_flags & SF_STR_LOCATE_END) aiff_write_strings (psf, SF_STR_LOCATE_END) ; /* Write the tailer. */ if (psf->headindex) psf_fwrite (psf->header, psf->headindex, 1, psf) ; return 0 ; } /* aiff_write_tailer */ static void aiff_write_strings (SF_PRIVATE *psf, int location) { int k ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) { if (psf->strings [k].type == 0) break ; if (psf->strings [k].flags != location) continue ; switch (psf->strings [k].type) { case SF_STR_SOFTWARE : psf_binheader_writef (psf, "Ems", APPL_MARKER, psf->strings [k].str) ; break ; case SF_STR_TITLE : psf_binheader_writef (psf, "Ems", NAME_MARKER, psf->strings [k].str) ; break ; case SF_STR_COPYRIGHT : psf_binheader_writef (psf, "Ems", c_MARKER, psf->strings [k].str) ; break ; case SF_STR_ARTIST : psf_binheader_writef (psf, "Ems", AUTH_MARKER, psf->strings [k].str) ; break ; case SF_STR_COMMENT : psf_binheader_writef (psf, "Ems", COMT_MARKER, psf->strings [k].str) ; break ; /* case SF_STR_DATE : psf_binheader_writef (psf, "Ems", ICRD_MARKER, psf->strings [k].str) ; break ; */ } ; } ; return ; } /* aiff_write_strings */ static int aiff_command (SF_PRIVATE *psf, int command, void *data, int datasize) { /* Avoid compiler warnings. */ psf = psf ; data = data ; datasize = datasize ; switch (command) { default : break ; } ; return 0 ; } /* aiff_command */ static const char* get_loop_mode_str (short mode) { switch (mode) { case 0 : return "none" ; case 1 : return "forward" ; case 2 : return "backward" ; } ; return "*** unknown" ; } /* get_loop_mode_str */ /*========================================================================================== ** Rough hack at converting from 80 bit IEEE float in AIFF header to an int and ** back again. It assumes that all sample rates are between 1 and 800MHz, which ** should be OK as other sound file formats use a 32 bit integer to store sample ** rate. ** There is another (probably better) version in the source code to the SoX but it ** has a copyright which probably prevents it from being allowable as GPL/LGPL. */ static int tenbytefloat2int (unsigned char *bytes) { int val = 3 ; if (bytes [0] & 0x80) /* Negative number. */ return 0 ; if (bytes [0] <= 0x3F) /* Less than 1. */ return 1 ; if (bytes [0] > 0x40) /* Way too big. */ return 0x4000000 ; if (bytes [0] == 0x40 && bytes [1] > 0x1C) /* Too big. */ return 800000000 ; /* Ok, can handle it. */ val = (bytes [2] << 23) | (bytes [3] << 15) | (bytes [4] << 7) | (bytes [5] >> 1) ; val >>= (29 - bytes [1]) ; return val ; } /* tenbytefloat2int */ static void uint2tenbytefloat (unsigned int num, unsigned char *bytes) { unsigned int mask = 0x40000000 ; int count ; memset (bytes, 0, 10) ; if (num <= 1) { bytes [0] = 0x3F ; bytes [1] = 0xFF ; bytes [2] = 0x80 ; return ; } ; bytes [0] = 0x40 ; if (num >= mask) { bytes [1] = 0x1D ; return ; } ; for (count = 0 ; count <= 32 ; count ++) { if (num & mask) break ; mask >>= 1 ; } ; num <<= count + 1 ; bytes [1] = 29 - count ; bytes [2] = (num >> 24) & 0xFF ; bytes [3] = (num >> 16) & 0xFF ; bytes [4] = (num >> 8) & 0xFF ; bytes [5] = num & 0xFF ; } /* uint2tenbytefloat */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 7dec56ca-d6f2-48cf-863b-a72e7e17a5d9 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static sf_count_t alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t alaw_write_s2alaw (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void alaw2s_array (unsigned char *buffer, unsigned int count, short *ptr) ; static void alaw2i_array (unsigned char *buffer, unsigned int count, int *ptr) ; static void alaw2f_array (unsigned char *buffer, unsigned int count, float *ptr, float normfact) ; static void alaw2d_array (unsigned char *buffer, unsigned int count, double *ptr, double normfact) ; static void s2alaw_array (short *buffer, unsigned int count, unsigned char *ptr) ; static void i2alaw_array (int *buffer, unsigned int count, unsigned char *ptr) ; static void f2alaw_array (float *buffer, unsigned int count, unsigned char *ptr, float normfact) ; static void d2alaw_array (double *buffer, unsigned int count, unsigned char *ptr, double normfact) ; int alaw_init (SF_PRIVATE *psf) { if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { psf->read_short = alaw_read_alaw2s ; psf->read_int = alaw_read_alaw2i ; psf->read_float = alaw_read_alaw2f ; psf->read_double = alaw_read_alaw2d ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->write_short = alaw_write_s2alaw ; psf->write_int = alaw_write_i2alaw ; psf->write_float = alaw_write_f2alaw ; psf->write_double = alaw_write_d2alaw ; } ; psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels ; if (psf->filelength > psf->dataoffset) psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; else psf->datalength = 0 ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* alaw_init */ static sf_count_t alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; alaw2s_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* alaw_read_alaw2s */ static sf_count_t alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; alaw2i_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* alaw_read_alaw2i */ static sf_count_t alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; alaw2f_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* alaw_read_alaw2f */ static sf_count_t alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; alaw2d_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* alaw_read_alaw2d */ /*============================================================================================= */ static sf_count_t alaw_write_s2alaw (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2alaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer)) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* alaw_write_s2alaw */ static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2alaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer)) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* alaw_write_i2alaw */ static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; f2alaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer), normfact) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* alaw_write_f2alaw */ static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; d2alaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer), normfact) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* alaw_write_d2alaw */ /*============================================================================================= * Private static functions and data. */ static short alaw_decode [128] = { -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944, -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136, -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472, -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568, -344, -328, -376, -360, -280, -264, -312, -296, -472, -456, -504, -488, -408, -392, -440, -424, -88, -72, -120, -104, -24, -8, -56, -40, -216, -200, -248, -232, -152, -136, -184, -168, -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, -688, -656, -752, -720, -560, -528, -624, -592, -944, -912, -1008, -976, -816, -784, -880, -848 } ; /* alaw_decode */ static unsigned char alaw_encode [2049] = { 0xD5, 0xD4, 0xD7, 0xD6, 0xD1, 0xD0, 0xD3, 0xD2, 0xDD, 0xDC, 0xDF, 0xDE, 0xD9, 0xD8, 0xDB, 0xDA, 0xC5, 0xC4, 0xC7, 0xC6, 0xC1, 0xC0, 0xC3, 0xC2, 0xCD, 0xCC, 0xCF, 0xCE, 0xC9, 0xC8, 0xCB, 0xCA, 0xF5, 0xF5, 0xF4, 0xF4, 0xF7, 0xF7, 0xF6, 0xF6, 0xF1, 0xF1, 0xF0, 0xF0, 0xF3, 0xF3, 0xF2, 0xF2, 0xFD, 0xFD, 0xFC, 0xFC, 0xFF, 0xFF, 0xFE, 0xFE, 0xF9, 0xF9, 0xF8, 0xF8, 0xFB, 0xFB, 0xFA, 0xFA, 0xE5, 0xE5, 0xE5, 0xE5, 0xE4, 0xE4, 0xE4, 0xE4, 0xE7, 0xE7, 0xE7, 0xE7, 0xE6, 0xE6, 0xE6, 0xE6, 0xE1, 0xE1, 0xE1, 0xE1, 0xE0, 0xE0, 0xE0, 0xE0, 0xE3, 0xE3, 0xE3, 0xE3, 0xE2, 0xE2, 0xE2, 0xE2, 0xED, 0xED, 0xED, 0xED, 0xEC, 0xEC, 0xEC, 0xEC, 0xEF, 0xEF, 0xEF, 0xEF, 0xEE, 0xEE, 0xEE, 0xEE, 0xE9, 0xE9, 0xE9, 0xE9, 0xE8, 0xE8, 0xE8, 0xE8, 0xEB, 0xEB, 0xEB, 0xEB, 0xEA, 0xEA, 0xEA, 0xEA, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x2A } ; /* alaw_encode */ static void alaw2s_array (unsigned char *buffer, unsigned int count, short *ptr) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -1 * alaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = alaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* alaw2s_array */ static void alaw2i_array (unsigned char *buffer, unsigned int count, int *ptr) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = (-1 * alaw_decode [((int) buffer [count]) & 0x7F]) << 16 ; else ptr [count] = alaw_decode [((int) buffer [count]) & 0x7F] << 16 ; } ; } /* alaw2i_array */ static void alaw2f_array (unsigned char *buffer, unsigned int count, float *ptr, float normfact) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -normfact * alaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = normfact * alaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* alaw2f_array */ static void alaw2d_array (unsigned char *buffer, unsigned int count, double *ptr, double normfact) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -normfact * alaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = normfact * alaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* alaw2d_array */ static void s2alaw_array (short *ptr, unsigned int count, unsigned char *buffer) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = alaw_encode [ptr [count] / 16] ; else buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ; } ; } /* s2alaw_array */ static void i2alaw_array (int *ptr, unsigned int count, unsigned char *buffer) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ; else buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ; } ; } /* i2alaw_array */ static void f2alaw_array (float *ptr, unsigned int count, unsigned char *buffer, float normfact) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = alaw_encode [(lrintf (normfact * ptr [count])) / 16] ; else buffer [count] = 0x7F & alaw_encode [(lrintf (normfact * ptr [count])) / -16] ; } ; } /* f2alaw_array */ static void d2alaw_array (double *ptr, unsigned int count, unsigned char *buffer, double normfact) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = alaw_encode [(lrint (normfact * ptr [count])) / 16] ; else buffer [count] = 0x7F & alaw_encode [(lrint (normfact * ptr [count])) / -16] ; } ; } /* d2alaw_array */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 289ccfc2-42a6-4f1f-a29f-4dcc9bfa8752 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd')) #define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.')) #define AU_DATA_OFFSET 24 /*------------------------------------------------------------------------------ ** Known AU file encoding types. */ enum { AU_ENCODING_ULAW_8 = 1, /* 8-bit u-law samples */ AU_ENCODING_PCM_8 = 2, /* 8-bit linear samples */ AU_ENCODING_PCM_16 = 3, /* 16-bit linear samples */ AU_ENCODING_PCM_24 = 4, /* 24-bit linear samples */ AU_ENCODING_PCM_32 = 5, /* 32-bit linear samples */ AU_ENCODING_FLOAT = 6, /* floating-point samples */ AU_ENCODING_DOUBLE = 7, /* double-precision float samples */ AU_ENCODING_INDIRECT = 8, /* fragmented sampled data */ AU_ENCODING_NESTED = 9, /* ? */ AU_ENCODING_DSP_CORE = 10, /* DSP program */ AU_ENCODING_DSP_DATA_8 = 11, /* 8-bit fixed-point samples */ AU_ENCODING_DSP_DATA_16 = 12, /* 16-bit fixed-point samples */ AU_ENCODING_DSP_DATA_24 = 13, /* 24-bit fixed-point samples */ AU_ENCODING_DSP_DATA_32 = 14, /* 32-bit fixed-point samples */ AU_ENCODING_DISPLAY = 16, /* non-audio display data */ AU_ENCODING_MULAW_SQUELCH = 17, /* ? */ AU_ENCODING_EMPHASIZED = 18, /* 16-bit linear with emphasis */ AU_ENCODING_NEXT = 19, /* 16-bit linear with compression (NEXT) */ AU_ENCODING_COMPRESSED_EMPHASIZED = 20, /* A combination of the two above */ AU_ENCODING_DSP_COMMANDS = 21, /* Music Kit DSP commands */ AU_ENCODING_DSP_COMMANDS_SAMPLES = 22, /* ? */ AU_ENCODING_ADPCM_G721_32 = 23, /* G721 32 kbs ADPCM - 4 bits per sample. */ AU_ENCODING_ADPCM_G722 = 24, /* G722 64 kbs ADPCM */ AU_ENCODING_ADPCM_G723_24 = 25, /* G723 24 kbs ADPCM - 3 bits per sample. */ AU_ENCODING_ADPCM_G723_40 = 26, /* G723 40 kbs ADPCM - 5 bits per sample. */ AU_ENCODING_ALAW_8 = 27 } ; /*------------------------------------------------------------------------------ ** Typedefs. */ typedef struct { int dataoffset ; int datasize ; int encoding ; int samplerate ; int channels ; } AU_FMT ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int au_close (SF_PRIVATE *psf) ; static int au_format_to_encoding (int format) ; static int au_write_header (SF_PRIVATE *psf, int calc_length) ; static int au_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int au_open (SF_PRIVATE *psf) { int subformat ; int error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = au_read_header (psf))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AU) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU) psf->endian = SF_ENDIAN_LITTLE ; else if (psf->endian != SF_ENDIAN_LITTLE) psf->endian = SF_ENDIAN_BIG ; if (au_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = au_write_header ; } ; psf->close = au_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */ ulaw_init (psf) ; break ; case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */ case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ error = pcm_init (psf) ; break ; case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */ alaw_init (psf) ; break ; /* Lite remove start */ case SF_FORMAT_FLOAT : /* 32-bit floats. */ error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : /* 64-bit double precision floats. */ error = double64_init (psf) ; break ; case SF_FORMAT_G721_32 : if (psf->mode == SFM_READ) error = au_g72x_reader_init (psf, AU_H_G721_32) ; else if (psf->mode == SFM_WRITE) error = au_g72x_writer_init (psf, AU_H_G721_32) ; psf->sf.seekable = SF_FALSE ; break ; case SF_FORMAT_G723_24 : if (psf->mode == SFM_READ) error = au_g72x_reader_init (psf, AU_H_G723_24) ; else if (psf->mode == SFM_WRITE) error = au_g72x_writer_init (psf, AU_H_G723_24) ; psf->sf.seekable = SF_FALSE ; break ; case SF_FORMAT_G723_40 : if (psf->mode == SFM_READ) error = au_g72x_reader_init (psf, AU_H_G723_40) ; else if (psf->mode == SFM_WRITE) error = au_g72x_writer_init (psf, AU_H_G723_40) ; psf->sf.seekable = SF_FALSE ; break ; /* Lite remove end */ default : break ; } ; return error ; } /* au_open */ int au_nh_open (SF_PRIVATE *psf) { if (psf->mode == SFM_RDWR) return SFE_BAD_OPEN_FORMAT ; if (psf_fseek (psf, psf->dataoffset, SEEK_SET)) return SFE_BAD_SEEK ; psf_log_printf (psf, "Header-less u-law encoded file.\n") ; psf_log_printf (psf, "Setting up for 8kHz, mono, u-law.\n") ; psf->sf.format = SF_FORMAT_AU | SF_FORMAT_ULAW ; psf->dataoffset = 0 ; psf->endian = 0 ; /* Irrelevant but it must be something. */ psf->sf.samplerate = 8000 ; psf->sf.channels = 1 ; psf->bytewidth = 1 ; /* Before decoding */ ulaw_init (psf) ; psf->close = au_close ; psf->blockwidth = 1 ; psf->sf.frames = psf->filelength ; psf->datalength = psf->filelength - AU_DATA_OFFSET ; return 0 ; } /* au_nh_open */ /*------------------------------------------------------------------------------ */ static int au_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) au_write_header (psf, SF_TRUE) ; return 0 ; } /* au_close */ static int au_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int encoding, datalength ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; encoding = au_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ; if (! encoding) return (psf->error = SFE_BAD_OPEN_FORMAT) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; /* ** Only attempt to seek if we are not writng to a pipe. If we are ** writing to a pipe we shouldn't be here anyway. */ if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; /* ** AU format files allow a datalength value of -1 if the datalength ** is not know at the time the header is written. ** Also use this value of -1 if the datalength > 2 gigabytes. */ if (psf->datalength < 0 || psf->datalength > 0x7FFFFFFF) datalength = -1 ; else datalength = (int) (psf->datalength & 0x7FFFFFFF) ; if (psf->endian == SF_ENDIAN_BIG) { psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ; psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ; psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ; } else return (psf->error = SFE_BAD_OPEN_FORMAT) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* au_write_header */ static int au_format_to_encoding (int format) { switch (format) { case SF_FORMAT_PCM_S8 : return AU_ENCODING_PCM_8 ; case SF_FORMAT_PCM_16 : return AU_ENCODING_PCM_16 ; case SF_FORMAT_PCM_24 : return AU_ENCODING_PCM_24 ; case SF_FORMAT_PCM_32 : return AU_ENCODING_PCM_32 ; case SF_FORMAT_FLOAT : return AU_ENCODING_FLOAT ; case SF_FORMAT_DOUBLE : return AU_ENCODING_DOUBLE ; case SF_FORMAT_ULAW : return AU_ENCODING_ULAW_8 ; case SF_FORMAT_ALAW : return AU_ENCODING_ALAW_8 ; case SF_FORMAT_G721_32 : return AU_ENCODING_ADPCM_G721_32 ; case SF_FORMAT_G723_24 : return AU_ENCODING_ADPCM_G723_24 ; case SF_FORMAT_G723_40 : return AU_ENCODING_ADPCM_G723_40 ; default : break ; } ; return 0 ; } /* au_format_to_encoding */ static int au_read_header (SF_PRIVATE *psf) { AU_FMT au_fmt ; int marker, dword ; psf_binheader_readf (psf, "pm", 0, &marker) ; psf_log_printf (psf, "%M\n", marker) ; if (marker == DOTSND_MARKER) { psf->endian = SF_ENDIAN_BIG ; psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize), &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; } else if (marker == DNSDOT_MARKER) { psf->endian = SF_ENDIAN_LITTLE ; psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize), &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; } else return SFE_AU_NO_DOTSND ; psf_log_printf (psf, " Data Offset : %d\n", au_fmt.dataoffset) ; if (psf->fileoffset > 0 && au_fmt.datasize == -1) { psf_log_printf (psf, " Data Size : -1\n") ; return SFE_AU_EMBED_BAD_LEN ; } ; if (psf->fileoffset > 0) { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; } else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength) psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength) { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; } else { dword = psf->filelength - au_fmt.dataoffset ; psf_log_printf (psf, " Data Size : %d (should be %d)\n", au_fmt.datasize, dword) ; au_fmt.datasize = dword ; } ; psf->dataoffset = au_fmt.dataoffset ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf_ftell (psf) < psf->dataoffset) psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; psf->close = au_close ; psf->sf.samplerate = au_fmt.samplerate ; psf->sf.channels = au_fmt.channels ; /* Only fill in type major. */ if (psf->endian == SF_ENDIAN_BIG) psf->sf.format = SF_FORMAT_AU ; else if (psf->endian == SF_ENDIAN_LITTLE) psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ; psf_log_printf (psf, " Encoding : %d => ", au_fmt.encoding) ; psf->sf.format = psf->sf.format & SF_FORMAT_ENDMASK ; switch (au_fmt.encoding) { case AU_ENCODING_ULAW_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ; psf->bytewidth = 1 ; /* Before decoding */ psf_log_printf (psf, "8-bit ISDN u-law\n") ; break ; case AU_ENCODING_PCM_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; psf_log_printf (psf, "8-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_16 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; psf_log_printf (psf, "16-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_24 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ; psf->bytewidth = 3 ; psf_log_printf (psf, "24-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_32 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; psf_log_printf (psf, "32-bit linear PCM\n") ; break ; case AU_ENCODING_FLOAT : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ; psf->bytewidth = 4 ; psf_log_printf (psf, "32-bit float\n") ; break ; case AU_ENCODING_DOUBLE : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ; psf->bytewidth = 8 ; psf_log_printf (psf, "64-bit double precision float\n") ; break ; case AU_ENCODING_ALAW_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ; psf->bytewidth = 1 ; /* Before decoding */ psf_log_printf (psf, "8-bit ISDN A-law\n") ; break ; case AU_ENCODING_ADPCM_G721_32 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G721 32kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G723_24 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G723 24kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G723_40 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G723 40kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G722 : psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ; break ; case AU_ENCODING_NEXT : psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ; break ; default : psf_log_printf (psf, "Unknown!!\n") ; break ; } ; psf_log_printf (psf, " Sample Rate : %d\n", au_fmt.samplerate) ; psf_log_printf (psf, " Channels : %d\n", au_fmt.channels) ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* au_read_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 31f691b1-cde9-4ed2-9469-6bca60fb9cd0 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include static int au_g72x_read_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) ; static int au_g72x_write_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) ; static int au_g72x_decode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) ; static int au_g72x_encode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) ; static sf_count_t au_g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t au_g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t au_g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t au_g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t au_g72x_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t au_g72x_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t au_g72x_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t au_g72x_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t au_g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int au_g72x_close (SF_PRIVATE *psf) ; /*============================================================================================ ** WAV G721 Reader initialisation function. */ int au_g72x_reader_init (SF_PRIVATE *psf, int codec) { G72x_DATA *pg72x ; int bitspersample ; psf->sf.seekable = SF_FALSE ; if (psf->sf.channels != 1) return SFE_G72X_NOT_MONO ; if (! (pg72x = malloc (sizeof (G72x_DATA)))) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pg72x ; pg72x->blockcount = 0 ; pg72x->samplecount = 0 ; switch (codec) { case AU_H_G721_32 : g72x_reader_init (pg72x, G721_32_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G721_32_BYTES_PER_BLOCK ; bitspersample = G721_32_BITS_PER_SAMPLE ; break ; case AU_H_G723_24: g72x_reader_init (pg72x, G723_24_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G723_24_BYTES_PER_BLOCK ; bitspersample = G723_24_BITS_PER_SAMPLE ; break ; case AU_H_G723_40: g72x_reader_init (pg72x, G723_40_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G723_40_BYTES_PER_BLOCK ; bitspersample = G723_40_BITS_PER_SAMPLE ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf->read_short = au_g72x_read_s ; psf->read_int = au_g72x_read_i ; psf->read_float = au_g72x_read_f ; psf->read_double = au_g72x_read_d ; psf->seek = au_g72x_seek ; psf->close = au_g72x_close ; psf->blockwidth = psf->bytewidth = 1 ; psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->datalength % pg72x->blocksize) pg72x->blocks = (psf->datalength / pg72x->blocksize) + 1 ; else pg72x->blocks = psf->datalength / pg72x->blocksize ; psf->sf.frames = (8 * psf->datalength) / bitspersample ; if ((psf->sf.frames * bitspersample) / 8 != psf->datalength) psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ; au_g72x_decode_block (psf, pg72x) ; return 0 ; } /* au_g72x_reader_init */ /*============================================================================================ ** WAV G721 writer initialisation function. */ int au_g72x_writer_init (SF_PRIVATE *psf, int codec) { G72x_DATA *pg72x ; int bitspersample ; psf->sf.seekable = SF_FALSE ; if (psf->sf.channels != 1) return SFE_G72X_NOT_MONO ; if (! (pg72x = malloc (sizeof (G72x_DATA)))) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pg72x ; pg72x->blockcount = 0 ; pg72x->samplecount = 0 ; switch (codec) { case AU_H_G721_32 : g72x_writer_init (pg72x, G721_32_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G721_32_BYTES_PER_BLOCK ; bitspersample = G721_32_BITS_PER_SAMPLE ; break ; case AU_H_G723_24: g72x_writer_init (pg72x, G723_24_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G723_24_BYTES_PER_BLOCK ; bitspersample = G723_24_BITS_PER_SAMPLE ; break ; case AU_H_G723_40: g72x_writer_init (pg72x, G723_40_BITS_PER_SAMPLE) ; pg72x->bytesperblock = G723_40_BYTES_PER_BLOCK ; bitspersample = G723_40_BITS_PER_SAMPLE ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf->write_short = au_g72x_write_s ; psf->write_int = au_g72x_write_i ; psf->write_float = au_g72x_write_f ; psf->write_double = au_g72x_write_d ; psf->close = au_g72x_close ; psf->blockwidth = psf->bytewidth = 1 ; psf->filelength = psf_get_filelen (psf) ; if (psf->filelength < psf->dataoffset) psf->filelength = psf->dataoffset ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->datalength % pg72x->blocksize) pg72x->blocks = (psf->datalength / pg72x->blocksize) + 1 ; else pg72x->blocks = psf->datalength / pg72x->blocksize ; if (psf->datalength > 0) psf->sf.frames = (8 * psf->datalength) / bitspersample ; if ((psf->sf.frames * bitspersample) / 8 != psf->datalength) psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ; return 0 ; } /* au_g72x_writer_init */ /*============================================================================================ ** G721 Read Functions. */ static int au_g72x_decode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) { int k ; pg72x->blockcount ++ ; pg72x->samplecount = 0 ; if (pg72x->samplecount > pg72x->blocksize) { memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ; return 1 ; } ; if ((k = psf_fread (pg72x->block, 1, pg72x->bytesperblock, psf)) != pg72x->bytesperblock) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pg72x->bytesperblock) ; pg72x->blocksize = k ; g72x_decode_block (pg72x) ; return 1 ; } /* au_g72x_decode_block */ static int au_g72x_read_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { if (pg72x->blockcount >= pg72x->blocks && pg72x->samplecount >= pg72x->samplesperblock) { memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ; return total ; } ; if (pg72x->samplecount >= pg72x->samplesperblock) au_g72x_decode_block (psf, pg72x) ; count = pg72x->samplesperblock - pg72x->samplecount ; count = (len - indx > count) ? count : len - indx ; memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->samplecount]), count * sizeof (short)) ; indx += count ; pg72x->samplecount += count ; total = indx ; } ; return total ; } /* au_g72x_read_block */ static sf_count_t au_g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { G72x_DATA *pg72x ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = au_g72x_read_block (psf, pg72x, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* au_g72x_read_s */ static sf_count_t au_g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = au_g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = sptr [k] << 16 ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* au_g72x_read_i */ static sf_count_t au_g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = au_g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* au_g72x_read_f */ static sf_count_t au_g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = au_g72x_read_block (psf, pg72x, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* au_g72x_read_d */ static sf_count_t au_g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { /* Prevent compiler warnings. */ mode ++ ; offset ++ ; psf_log_printf (psf, "seek unsupported\n") ; /* No simple solution. To do properly, would need to seek ** to start of file and decode everything up to seek position. ** Maybe implement SEEK_SET to 0 only? */ return 0 ; /* ** G72x_DATA *pg72x ; ** int newblock, newsample, samplecount ; ** ** if (! psf->fdata) ** return 0 ; ** pg72x = (G72x_DATA*) psf->fdata ; ** ** if (! (psf->datalength && psf->dataoffset)) ** { psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** ** samplecount = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ; ** ** switch (whence) ** { case SEEK_SET : ** if (offset < 0 || offset > samplecount) ** { psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** newblock = offset / pg72x->samplesperblock ; ** newsample = offset % pg72x->samplesperblock ; ** break ; ** ** case SEEK_CUR : ** if (psf->current + offset < 0 || psf->current + offset > samplecount) ** { psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ; ** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ; ** break ; ** ** case SEEK_END : ** if (offset > 0 || samplecount + offset < 0) ** { psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** newblock = (samplecount + offset) / pg72x->samplesperblock ; ** newsample = (samplecount + offset) % pg72x->samplesperblock ; ** break ; ** ** default : ** psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** ** if (psf->mode == SFM_READ) ** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ; ** pg72x->blockcount = newblock ; ** au_g72x_decode_block (psf, pg72x) ; ** pg72x->samplecount = newsample ; ** } ** else ** { /+* What to do about write??? *+/ ** psf->error = SFE_BAD_SEEK ; ** return ((sf_count_t) -1) ; ** } ; ** ** psf->current = newblock * pg72x->samplesperblock + newsample ; ** return psf->current ; ** */ } /* au_g72x_seek */ /*========================================================================================== ** G72x Write Functions. */ static int au_g72x_encode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) { int k ; /* Encode the samples. */ g72x_encode_block (pg72x) ; /* Write the block to disk. */ if ((k = psf_fwrite (pg72x->block, 1, pg72x->blocksize, psf)) != pg72x->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pg72x->blocksize) ; pg72x->samplecount = 0 ; pg72x->blockcount ++ ; /* Set samples to zero for next block. */ memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ; return 1 ; } /* au_g72x_encode_block */ static int au_g72x_write_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { count = pg72x->samplesperblock - pg72x->samplecount ; if (count > len - indx) count = len - indx ; memcpy (&(pg72x->samples [pg72x->samplecount]), &(ptr [indx]), count * sizeof (short)) ; indx += count ; pg72x->samplecount += count ; total = indx ; if (pg72x->samplecount >= pg72x->samplesperblock) au_g72x_encode_block (psf, pg72x) ; } ; return total ; } /* au_g72x_write_block */ static sf_count_t au_g72x_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { G72x_DATA *pg72x ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = au_g72x_write_block (psf, pg72x, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* au_g72x_write_s */ static sf_count_t au_g72x_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = au_g72x_write_block (psf, pg72x, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* au_g72x_write_i */ static sf_count_t au_g72x_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrintf (normfact * ptr [total + k]) ; count = au_g72x_write_block (psf, pg72x, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* au_g72x_write_f */ static sf_count_t au_g72x_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { G72x_DATA *pg72x ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrint (normfact * ptr [total + k]) ; count = au_g72x_write_block (psf, pg72x, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* au_g72x_write_d */ static int au_g72x_close (SF_PRIVATE *psf) { G72x_DATA *pg72x ; if (! psf->fdata) return 0 ; pg72x = (G72x_DATA*) psf->fdata ; if (psf->mode == SFM_WRITE) { /* If a block has been partially assembled, write it out ** as the final block. */ if (pg72x->samplecount && pg72x->samplecount < G72x_BLOCK_SIZE) au_g72x_encode_block (psf, pg72x) ; if (psf->write_header) psf->write_header (psf, SF_FALSE) ; } ; return 0 ; } /* au_g72x_close */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 3cc5439e-7247-486b-b2e6-11a4affa5744 */ /* ** Copyright (C) 2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T')) #define AVR_HDR_SIZE 128 #define SFE_AVR_X 666 /* ** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu) ** ** A lot of PD software exists to play Mac .snd files on the ST. One other ** format that seems pretty popular (used by a number of commercial packages) ** is the AVR format (from Audio Visual Research). This format has a 128 byte ** header that looks like this (its actually packed, but thats not portable): */ typedef struct { int marker ; /* 2BIT */ char name [8] ; /* null-padded sample name */ short mono ; /* 0 = mono, 0xffff = stereo */ short rez ; /* 8 = 8 bit, 16 = 16 bit */ short sign ; /* 0 = unsigned, 0xffff = signed */ short loop ; /* 0 = no loop, 0xffff = looping sample */ short midi ; /* 0xffff = no MIDI note assigned, */ /* 0xffXX = single key note assignment */ /* 0xLLHH = key split, low/hi note */ int srate ; /* sample frequency in hertz */ int frames ; /* sample length in bytes or words (see rez) */ int lbeg ; /* offset to start of loop in bytes or words. */ /* set to zero if unused */ int lend ; /* offset to end of loop in bytes or words. */ /* set to sample length if unused */ short res1 ; /* Reserved, MIDI keyboard split */ short res2 ; /* Reserved, sample compression */ short res3 ; /* Reserved */ char ext [20] ; /* Additional filename space, used if (name[7] != 0) */ char user [64] ; /* User defined. Typically ASCII message */ } AVR_HEADER ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int avr_close (SF_PRIVATE *psf) ; static int avr_read_header (SF_PRIVATE *psf) ; static int avr_write_header (SF_PRIVATE *psf, int calc_length) ; /*------------------------------------------------------------------------------ ** Public function. */ int avr_open (SF_PRIVATE *psf) { int subformat ; int error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = avr_read_header (psf))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AVR) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; psf->endian = SF_ENDIAN_BIG ; if (avr_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = avr_write_header ; } ; psf->close = avr_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; error = pcm_init (psf) ; return error ; } /* avr_open */ static int avr_read_header (SF_PRIVATE *psf) { AVR_HEADER hdr ; memset (&hdr, 0, sizeof (hdr)) ; psf_binheader_readf (psf, "pmb", 0, &hdr.marker, &hdr.name, sizeof (hdr.name)) ; psf_log_printf (psf, "%M\n", hdr.marker) ; if (hdr.marker != TWOBIT_MARKER) return SFE_AVR_X ; psf_log_printf (psf, " Name : %s\n", hdr.name) ; psf_binheader_readf (psf, "E22222", &hdr.mono, &hdr.rez, &hdr.sign, &hdr.loop, &hdr.midi) ; psf->sf.channels = (hdr.mono & 1) + 1 ; psf_log_printf (psf, " Channels : %d\n Bit width : %d\n Signed : %s\n", (hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ; switch ((hdr.rez << 16) + (hdr.sign & 1)) { case ((8 << 16) + 0) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ; psf->bytewidth = 1 ; break ; case ((8 << 16) + 1) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case ((16 << 16) + 1) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; return SFE_AVR_X ; break ; } ; psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ; psf->sf.frames = hdr.frames ; psf->sf.samplerate = hdr.srate ; psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ; psf_binheader_readf (psf, "E222", &hdr.res1, &hdr.res2, &hdr.res3) ; psf_binheader_readf (psf, "bb", hdr.ext, sizeof (hdr.ext), hdr.user, sizeof (hdr.user)) ; psf_log_printf (psf, " Ext : %s\n User : %s\n", hdr.ext, hdr.user) ; psf->endian = SF_ENDIAN_BIG ; psf->dataoffset = AVR_HDR_SIZE ; psf->datalength = hdr.frames * (hdr.rez / 8) ; if (psf->fileoffset > 0) psf->filelength = AVR_HDR_SIZE + psf->datalength ; if (psf_ftell (psf) != psf->dataoffset) psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; psf->close = avr_close ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (psf->sf.frames == 0 && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* avr_read_header */ static int avr_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int sign, datalength ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; /* ** Only attempt to seek if we are not writng to a pipe. If we are ** writing to a pipe we shouldn't be here anyway. */ if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; datalength = (int) (psf->datalength & 0x7FFFFFFF) ; psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, (size_t) 8, psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ; sign = ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ; psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ; psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ; psf_binheader_writef (psf, "E222zz", 0, 0, 0, (size_t) 20, (size_t) 64) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* avr_write_header */ static int avr_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) avr_write_header (psf, SF_TRUE) ; return 0 ; } /* avr_close */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 0823d454-f39a-4a28-a776-607f1ef33b52 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* * 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER */ void Gsm_Coder ( struct gsm_state * State, word * s, /* [0..159] samples IN */ /* * The RPE-LTD coder works on a frame by frame basis. The length of * the frame is equal to 160 samples. Some computations are done * once per frame to produce at the output of the coder the * LARc[1..8] parameters which are the coded LAR coefficients and * also to realize the inverse filtering operation for the entire * frame (160 samples of signal d[0..159]). These parts produce at * the output of the coder: */ word * LARc, /* [0..7] LAR coefficients OUT */ /* * Procedure 4.2.11 to 4.2.18 are to be executed four times per * frame. That means once for each sub-segment RPE-LTP analysis of * 40 samples. These parts produce at the output of the coder: */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc /* [13*4] normalized RPE samples OUT */ ) { int k; word * dp = State->dp0 + 120; /* [ -120...-1 ] */ word * dpp = dp; /* [ 0...39 ] */ word so[160]; Gsm_Preprocess (State, s, so); Gsm_LPC_Analysis (State, so, LARc); Gsm_Short_Term_Analysis_Filter (State, LARc, so); for (k = 0; k <= 3; k++, xMc += 13) { Gsm_Long_Term_Predictor ( State, so+k*40, /* d [0..39] IN */ dp, /* dp [-120..-1] IN */ State->e + 5, /* e [0..39] OUT */ dpp, /* dpp [0..39] OUT */ Nc++, bc++); Gsm_RPE_Encoding ( /*-S,-*/ State->e + 5, /* e ][0..39][ IN/OUT */ xmaxc++, Mc++, xMc ); /* * Gsm_Update_of_reconstructed_short_time_residual_signal * ( dpp, e + 5, dp ); */ { register int i; for (i = 0; i <= 39; i++) dp[ i ] = GSM_ADD( State->e[5 + i], dpp[i] ); } dp += 40; dpp += 40; } (void)memcpy( (char *)State->dp0, (char *)(State->dp0 + 160), 120 * sizeof(*State->dp0) ); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: ae8ef1b2-5a1e-4263-94cd-42b15dca81a3 */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include static SF_FORMAT_INFO const simple_formats [] = { { SF_FORMAT_AIFF | SF_FORMAT_PCM_16, "AIFF (Apple/SGI 16 bit PCM)", "aiff" }, { SF_FORMAT_AIFF | SF_FORMAT_FLOAT, "AIFF (Apple/SGI 32 bit float)", "aifc" }, { SF_FORMAT_AIFF | SF_FORMAT_PCM_S8, "AIFF (Apple/SGI 8 bit PCM)", "aiff" }, { SF_FORMAT_AU | SF_FORMAT_PCM_16, "AU (Sun/Next 16 bit PCM)", "au" }, { SF_FORMAT_AU | SF_FORMAT_ULAW, "AU (Sun/Next 8-bit u-law)", "au" }, { SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, "OKI Dialogic VOX ADPCM", "vox" }, { SF_FORMAT_WAV | SF_FORMAT_PCM_16, "WAV (Microsoft 16 bit PCM)", "wav" }, { SF_FORMAT_WAV | SF_FORMAT_FLOAT, "WAV (Microsoft 32 bit float)", "wav" }, { SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, "WAV (Microsoft 4 bit IMA ADPCM)", "wav" }, { SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, "WAV (Microsoft 4 bit MS ADPCM)", "wav" }, { SF_FORMAT_WAV | SF_FORMAT_PCM_U8, "WAV (Microsoft 8 bit PCM)", "wav" }, } ; /* simple_formats */ int psf_get_format_simple_count (void) { return (sizeof (simple_formats) / sizeof (SF_FORMAT_INFO)) ; } /* psf_get_format_simple_count */ int psf_get_format_simple (SF_FORMAT_INFO *data) { int indx ; if (data->format < 0 || data->format >= (SIGNED_SIZEOF (simple_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) return SFE_BAD_CONTROL_CMD ; indx = data->format ; memcpy (data, &(simple_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ; return 0 ; } /* psf_get_format_simple */ /*============================================================================ ** Major format info. */ static SF_FORMAT_INFO const major_formats [] = { { SF_FORMAT_AIFF, "AIFF (Apple/SGI)", "aiff" }, { SF_FORMAT_AU, "AU (Sun/NeXT)", "au" }, { SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" }, { SF_FORMAT_HTK, "HTK (HMM Tool Kit)", "htk" }, { SF_FORMAT_SVX, "IFF (Amiga IFF/SVX8/SV16)", "iff" }, { SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" }, { SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" }, { SF_FORMAT_PAF, "PAF (Ensoniq PARIS)", "paf" }, { SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" }, { SF_FORMAT_RAW, "RAW (header-less)", "raw" }, { SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" }, /* Not ready for mainstream use yet. { SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" }, */ { SF_FORMAT_IRCAM, "SF (Berkeley/IRCAM/CARL)", "sf" }, { SF_FORMAT_VOC, "VOC (Creative Labs)", "voc" }, { SF_FORMAT_W64, "W64 (SoundFoundry WAVE 64)", "w64" }, { SF_FORMAT_WAV, "WAV (Microsoft)", "wav" }, { SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" }, { SF_FORMAT_WAVEX, "WAVEX (Microsoft)", "wav" }, { SF_FORMAT_XI, "XI (FastTracker 2)", "xi" }, } ; /* major_formats */ int psf_get_format_major_count (void) { return (sizeof (major_formats) / sizeof (SF_FORMAT_INFO)) ; } /* psf_get_format_major_count */ int psf_get_format_major (SF_FORMAT_INFO *data) { int indx ; if (data->format < 0 || data->format >= (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) return SFE_BAD_CONTROL_CMD ; indx = data->format ; memcpy (data, &(major_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ; return 0 ; } /* psf_get_format_major */ /*============================================================================ ** Subtype format info. */ static SF_FORMAT_INFO subtype_formats [] = { { SF_FORMAT_PCM_S8, "Signed 8 bit PCM", NULL }, { SF_FORMAT_PCM_16, "Signed 16 bit PCM", NULL }, { SF_FORMAT_PCM_24, "Signed 24 bit PCM", NULL }, { SF_FORMAT_PCM_32, "Signed 32 bit PCM", NULL }, { SF_FORMAT_PCM_U8, "Unsigned 8 bit PCM", NULL }, { SF_FORMAT_FLOAT, "32 bit float", NULL }, { SF_FORMAT_DOUBLE, "64 bit float", NULL }, { SF_FORMAT_ULAW, "U-Law", NULL }, { SF_FORMAT_ALAW, "A-Law", NULL }, { SF_FORMAT_IMA_ADPCM, "IMA ADPCM", NULL }, { SF_FORMAT_MS_ADPCM, "Microsoft ADPCM", NULL }, { SF_FORMAT_GSM610, "GSM 6.10", NULL }, { SF_FORMAT_G721_32, "32kbs G721 ADPCM", NULL }, { SF_FORMAT_G723_24, "24kbs G723 ADPCM", NULL }, { SF_FORMAT_DWVW_12, "12 bit DWVW", NULL }, { SF_FORMAT_DWVW_16, "16 bit DWVW", NULL }, { SF_FORMAT_DWVW_24, "24 bit DWVW", NULL }, { SF_FORMAT_VOX_ADPCM, "VOX ADPCM", "vox" }, { SF_FORMAT_DPCM_16, "16 bit DPCM", NULL }, { SF_FORMAT_DPCM_8, "8 bit DPCM", NULL }, } ; /* subtype_formats */ int psf_get_format_subtype_count (void) { return (sizeof (subtype_formats) / sizeof (SF_FORMAT_INFO)) ; } /* psf_get_format_subtype_count */ int psf_get_format_subtype (SF_FORMAT_INFO *data) { int indx ; if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO))) return SFE_BAD_CONTROL_CMD ; indx = data->format ; memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ; return 0 ; } /* psf_get_format_subtype */ /*============================================================================== */ int psf_get_format_info (SF_FORMAT_INFO *data) { int k, format ; if (data->format & SF_FORMAT_TYPEMASK) { format = data->format & SF_FORMAT_TYPEMASK ; for (k = 0 ; k < (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++) { if (format == major_formats [k].format) { memcpy (data, &(major_formats [k]), sizeof (SF_FORMAT_INFO)) ; return 0 ; } ; } ; } else if (data->format & SF_FORMAT_SUBMASK) { format = data->format & SF_FORMAT_SUBMASK ; for (k = 0 ; k < (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++) { if (format == subtype_formats [k].format) { memcpy (data, &(subtype_formats [k]), sizeof (SF_FORMAT_INFO)) ; return 0 ; } ; } ; } ; memset (data, 0, sizeof (SF_FORMAT_INFO)) ; return SFE_BAD_CONTROL_CMD ; } /* psf_get_format_info */ /*============================================================================== */ double psf_calc_signal_max (SF_PRIVATE *psf, int normalize) { sf_count_t position ; double max_val = 0.0, temp, *data ; int k, len, readcount, save_state ; /* If the file is not seekable, there is nothing we can do. */ if (! psf->sf.seekable) { psf->error = SFE_NOT_SEEKABLE ; return 0.0 ; } ; if (! psf->read_double) { psf->error = SFE_UNIMPLEMENTED ; return 0.0 ; } ; save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ; sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ; /* Brute force. Read the whole file and find the biggest sample. */ position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */ sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */ len = sizeof (psf->buffer) / sizeof (double) ; data = (double*) psf->buffer ; readcount = len ; while (readcount > 0) { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; for (k = 0 ; k < readcount ; k++) { temp = fabs (data [k]) ; max_val = temp > max_val ? temp : max_val ; } ; } ; sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; /* Return to original position. */ sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ; return max_val ; } /* psf_calc_signal_max */ int psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) { sf_count_t position ; double temp, *data ; int k, len, readcount, save_state ; int chan ; /* If the file is not seekable, there is nothing we can do. */ if (! psf->sf.seekable) return (psf->error = SFE_NOT_SEEKABLE) ; if (! psf->read_double) return (psf->error = SFE_UNIMPLEMENTED) ; save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ; sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ; memset (peaks, 0, sizeof (double) * psf->sf.channels) ; /* Brute force. Read the whole file and find the biggest sample for each channel. */ position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */ sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */ len = sizeof (psf->buffer) / sizeof (double) ; data = (double*) psf->buffer ; chan = 0 ; readcount = len ; while (readcount > 0) { readcount = sf_read_double ((SNDFILE*) psf, data, len) ; for (k = 0 ; k < readcount ; k++) { temp = fabs (data [k]) ; peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ; chan = (chan + 1) % psf->sf.channels ; } ; } ; sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; /* Return to original position. */ sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ; return 0 ; } /* psf_calc_signal_max */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 0aae0d9d-ab2b-4d70-ade3-47a534666f8e */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /*----------------------------------------------------------------------------------------------- ** psf_log_printf allows libsndfile internal functions to print to an internal logbuffer which ** can later be displayed. ** The format specifiers are as for printf but without the field width and other modifiers. ** Printing is performed to the logbuffer char array of the SF_PRIVATE struct. ** Printing is done in such a way as to guarantee that the log never overflows the end of the ** logbuffer array. */ #define LOG_PUTCHAR(a,b) \ { if ((a)->logindex < SIGNED_SIZEOF ((a)->logbuffer) - 1)\ { (a)->logbuffer [(a)->logindex++] = (b) ; \ (a)->logbuffer [(a)->logindex] = 0 ; \ } \ } void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) { va_list ap ; unsigned int u ; int d, tens, shift, width, width_specifier, left_align ; char c, *strptr, istr [5], lead_char, sign_char ; va_start (ap, format) ; while ((c = *format++)) { if (c != '%') { LOG_PUTCHAR (psf, c) ; continue ; } ; if (format [0] == '%') /* Handle %% */ { LOG_PUTCHAR (psf, '%') ; format ++ ; continue ; } ; sign_char = 0 ; left_align = SF_FALSE ; while (1) { switch (format [0]) { case ' ' : case '+' : sign_char = format [0] ; format ++ ; continue ; case '-' : left_align = SF_TRUE ; format ++ ; continue ; default : break ; } ; break ; } ; if (format [0] == 0) break ; lead_char = ' ' ; if (format [0] == '0') lead_char = '0' ; width_specifier = 0 ; while ((c = *format++) && isdigit (c)) width_specifier = width_specifier * 10 + (c - '0') ; switch (c) { case 0 : /* NULL character. */ va_end (ap) ; return ; case 's': /* string */ strptr = va_arg (ap, char *) ; if (strptr == NULL) break ; width_specifier -= strlen (strptr) ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, ' ') ; while (*strptr) LOG_PUTCHAR (psf, *strptr++) ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, ' ') ; break ; case 'd': /* int */ d = va_arg (ap, int) ; if (d < 0) { d = -d ; sign_char = '-' ; if (lead_char != '0' && left_align == SF_FALSE) width_specifier -- ; } ; tens = 1 ; width = 1 ; while (d / tens >= 10) { tens *= 10 ; width ++ ; } ; width_specifier -= width ; if (sign_char == ' ') { LOG_PUTCHAR (psf, ' ') ; width_specifier -- ; } ; if (left_align == SF_FALSE && lead_char != '0') { if (sign_char == '+') width_specifier -- ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; } ; if (sign_char == '+' || sign_char == '-') { LOG_PUTCHAR (psf, sign_char) ; width_specifier -- ; } ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; while (tens > 0) { LOG_PUTCHAR (psf, '0' + d / tens) ; d %= tens ; tens /= 10 ; } ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; break ; case 'D': /* sf_count_t */ { sf_count_t D, Tens ; D = va_arg (ap, sf_count_t) ; if (D == 0) { while (-- width_specifier > 0) LOG_PUTCHAR (psf, lead_char) ; LOG_PUTCHAR (psf, '0') ; break ; } if (D < 0) { LOG_PUTCHAR (psf, '-') ; D = -D ; } ; Tens = 1 ; width = 1 ; while (D / Tens >= 10) { Tens *= 10 ; width ++ ; } ; while (width_specifier > width) { LOG_PUTCHAR (psf, lead_char) ; width_specifier-- ; } ; while (Tens > 0) { LOG_PUTCHAR (psf, '0' + D / Tens) ; D %= Tens ; Tens /= 10 ; } ; } ; break ; case 'u': /* unsigned int */ u = va_arg (ap, unsigned int) ; tens = 1 ; width = 1 ; while (u / tens >= 10) { tens *= 10 ; width ++ ; } ; width_specifier -= width ; if (sign_char == ' ') { LOG_PUTCHAR (psf, ' ') ; width_specifier -- ; } ; if (left_align == SF_FALSE && lead_char != '0') { if (sign_char == '+') width_specifier -- ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; } ; if (sign_char == '+' || sign_char == '-') { LOG_PUTCHAR (psf, sign_char) ; width_specifier -- ; } ; if (left_align == SF_FALSE) while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; while (tens > 0) { LOG_PUTCHAR (psf, '0' + u / tens) ; u %= tens ; tens /= 10 ; } ; while (width_specifier -- > 0) LOG_PUTCHAR (psf, lead_char) ; break ; case 'c': /* char */ c = va_arg (ap, int) & 0xFF ; LOG_PUTCHAR (psf, c) ; break ; case 'X': /* hex */ d = va_arg (ap, int) ; if (d == 0) { while (--width_specifier > 0) LOG_PUTCHAR (psf, lead_char) ; LOG_PUTCHAR (psf, '0') ; break ; } ; shift = 28 ; width = (width_specifier < 8) ? 8 : width_specifier ; while (! ((0xF << shift) & d)) { shift -= 4 ; width -- ; } ; while (width > 0 && width_specifier > width) { LOG_PUTCHAR (psf, lead_char) ; width_specifier-- ; } ; while (shift >= 0) { c = (d >> shift) & 0xF ; LOG_PUTCHAR (psf, (c > 9) ? c + 'A' - 10 : c + '0') ; shift -= 4 ; } ; break ; case 'M': /* int2str */ d = va_arg (ap, int) ; if (CPU_IS_LITTLE_ENDIAN) { istr [0] = d & 0xFF ; istr [1] = (d >> 8) & 0xFF ; istr [2] = (d >> 16) & 0xFF ; istr [3] = (d >> 24) & 0xFF ; } else { istr [3] = d & 0xFF ; istr [2] = (d >> 8) & 0xFF ; istr [1] = (d >> 16) & 0xFF ; istr [0] = (d >> 24) & 0xFF ; } ; istr [4] = 0 ; strptr = istr ; while (*strptr) { c = *strptr++ ; LOG_PUTCHAR (psf, c) ; } ; break ; default : LOG_PUTCHAR (psf, '*') ; LOG_PUTCHAR (psf, c) ; LOG_PUTCHAR (psf, '*') ; break ; } /* switch */ } /* while */ va_end (ap) ; return ; } /* psf_log_printf */ #ifndef PSF_LOG_PRINTF_ONLY /*----------------------------------------------------------------------------------------------- ** ASCII header printf functions. ** Some formats (ie NIST) use ascii text in their headers. ** Format specifiers are the same as the standard printf specifiers (uses vsnprintf). ** If this generates a compile error on any system, the author should be notified ** so an alternative vsnprintf can be provided. */ void psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) { va_list argptr ; int maxlen ; char *start ; maxlen = strlen ((char*) psf->header) ; start = ((char*) psf->header) + maxlen ; maxlen = sizeof (psf->header) - maxlen ; va_start (argptr, format) ; LSF_VSNPRINTF (start, maxlen, format, argptr) ; va_end (argptr) ; /* Make sure the string is properly terminated. */ start [maxlen - 1] = 0 ; psf->headindex = strlen ((char*) psf->header) ; return ; } /* psf_asciiheader_printf */ /*----------------------------------------------------------------------------------------------- ** Binary header writing functions. Returns number of bytes written. ** ** Format specifiers for psf_binheader_writef are as follows ** m - marker - four bytes - no endian manipulation ** ** e - all following numerical values will be little endian ** E - all following numerical values will be big endian ** ** t - all following O types will be truncated to 4 bytes ** T - switch off truncation of all following O types ** ** 1 - single byte value ** 2 - two byte value ** 3 - three byte value ** 4 - four byte value ** 8 - eight byte value (sometimes written as 4 bytes) ** ** s - string preceded by a four byte length ** S - string including null terminator ** f - floating point data ** d - double precision floating point data ** h - 16 binary bytes value ** ** b - binary data (see below) ** z - zero bytes (ses below) ** j - jump forwards or backwards ** ** To write a word followed by an int (both little endian) use: ** psf_binheader_writef ("e24", wordval, longval) ; ** ** To write binary data use: ** psf_binheader_writef ("b", &bindata, sizeof (bindata)) ; ** ** To write N zero bytes use: ** psf_binheader_writef ("z", N) ; */ /* These macros may seem a bit messy but do prevent problems with processors which ** seg. fault when asked to write an int or short to a non-int/short aligned address. */ #define PUT_BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 1) \ { (psf)->header [(psf)->headindex++] = (x) ; } #if (CPU_IS_BIG_ENDIAN == 1) #define PUT_MARKER(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #elif (CPU_IS_LITTLE_ENDIAN == 1) #define PUT_MARKER(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; } #else # error "Cannot determine endian-ness of processor." #endif #define PUT_BE_SHORT(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 2) \ { (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #define PUT_LE_SHORT(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 2) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; } #define PUT_BE_3BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 3) \ { (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #define PUT_LE_3BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 3) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; } #define PUT_BE_INT(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #define PUT_LE_INT(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 4) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; } #if (SIZEOF_SF_COUNT_T == 4) #define PUT_BE_8BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 8) \ { (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #define PUT_LE_8BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 8) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; \ (psf)->header [(psf)->headindex++] = 0 ; } #elif (SIZEOF_SF_COUNT_T == 8) #define PUT_BE_8BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 8) \ { (psf)->header [(psf)->headindex++] = ((x) >> 56) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 48) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 40) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 32) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = (x) ; } #define PUT_LE_8BYTE(psf,x) if ((psf)->headindex < SIGNED_SIZEOF ((psf)->header) - 8) \ { (psf)->header [(psf)->headindex++] = (x) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 8) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 16) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 24) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 32) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 40) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 48) ; \ (psf)->header [(psf)->headindex++] = ((x) >> 56) ; } #else #error "SIZEOF_SF_COUNT_T is not defined." #endif int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) { va_list argptr ; sf_count_t countdata ; unsigned long longdata ; unsigned int data ; float floatdata ; double doubledata ; void *bindata ; size_t size ; char c, *strptr ; int count = 0, trunc_8to4 ; trunc_8to4 = SF_FALSE ; va_start (argptr, format) ; while ((c = *format++)) { switch (c) { case 'e' : /* All conversions are now from LE to host. */ psf->rwf_endian = SF_ENDIAN_LITTLE ; break ; case 'E' : /* All conversions are now from BE to host. */ psf->rwf_endian = SF_ENDIAN_BIG ; break ; case 't' : /* All 8 byte values now get written as 4 bytes. */ trunc_8to4 = SF_TRUE ; break ; case 'T' : /* All 8 byte values now get written as 8 bytes. */ trunc_8to4 = SF_FALSE ; break ; case 'm' : data = va_arg (argptr, unsigned int) ; PUT_MARKER (psf, data) ; count += 4 ; break ; case '1' : data = va_arg (argptr, unsigned int) ; PUT_BYTE (psf, data) ; count += 1 ; break ; case '2' : data = va_arg (argptr, unsigned int) ; if (psf->rwf_endian == SF_ENDIAN_BIG) { PUT_BE_SHORT (psf, data) ; } else { PUT_LE_SHORT (psf, data) ; } ; count += 2 ; break ; case '3' : /* tribyte */ data = va_arg (argptr, unsigned int) ; if (psf->rwf_endian == SF_ENDIAN_BIG) { PUT_BE_3BYTE (psf, data) ; } else { PUT_LE_3BYTE (psf, data) ; } ; count += 3 ; break ; case '4' : data = va_arg (argptr, unsigned int) ; if (psf->rwf_endian == SF_ENDIAN_BIG) { PUT_BE_INT (psf, data) ; } else { PUT_LE_INT (psf, data) ; } ; count += 4 ; break ; case '8' : countdata = va_arg (argptr, sf_count_t) ; if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_FALSE) { PUT_BE_8BYTE (psf, countdata) ; count += 8 ; } else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_FALSE) { PUT_LE_8BYTE (psf, countdata) ; count += 8 ; } else if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_TRUE) { longdata = countdata & 0xFFFFFFFF ; PUT_BE_INT (psf, longdata) ; count += 4 ; } else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_TRUE) { longdata = countdata & 0xFFFFFFFF ; PUT_LE_INT (psf, longdata) ; count += 4 ; } break ; case 'f' : /* Floats are passed as doubles. Is this always true? */ floatdata = (float) va_arg (argptr, double) ; if (psf->rwf_endian == SF_ENDIAN_BIG) float32_be_write (floatdata, psf->header + psf->headindex) ; else float32_le_write (floatdata, psf->header + psf->headindex) ; psf->headindex += 4 ; count += 4 ; break ; case 'd' : doubledata = va_arg (argptr, double) ; if (psf->rwf_endian == SF_ENDIAN_BIG) double64_be_write (doubledata, psf->header + psf->headindex) ; else double64_le_write (doubledata, psf->header + psf->headindex) ; psf->headindex += 8 ; count += 8 ; break ; case 's' : strptr = va_arg (argptr, char *) ; size = strlen (strptr) + 1 ; size += (size & 1) ; if (psf->rwf_endian == SF_ENDIAN_BIG) { PUT_BE_INT (psf, size) ; } else { PUT_LE_INT (psf, size) ; } ; memcpy (&(psf->header [psf->headindex]), strptr, size) ; psf->headindex += size ; psf->header [psf->headindex - 1] = 0 ; count += 4 + size ; break ; case 'S' : strptr = va_arg (argptr, char *) ; size = strlen (strptr) + 1 ; memcpy (&(psf->header [psf->headindex]), strptr, size) ; psf->headindex += size ; count += size ; break ; case 'b' : bindata = va_arg (argptr, void *) ; size = va_arg (argptr, size_t) ; memcpy (&(psf->header [psf->headindex]), bindata, size) ; psf->headindex += size ; count += size ; break ; case 'z' : size = va_arg (argptr, size_t) ; count += size ; while (size) { psf->header [psf->headindex] = 0 ; psf->headindex ++ ; size -- ; } ; break ; case 'h' : bindata = va_arg (argptr, void *) ; memcpy (&(psf->header [psf->headindex]), bindata, 16) ; psf->headindex += 16 ; count += 16 ; break ; case 'j' : size = va_arg (argptr, int) ; psf->headindex += size ; count = size ; break ; default : psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; psf->error = SFE_INTERNAL ; break ; } ; } ; va_end (argptr) ; return count ; } /* psf_binheader_writef */ /*----------------------------------------------------------------------------------------------- ** Binary header reading functions. Returns number of bytes read. ** ** Format specifiers are the same as for header write function above with the following ** additions: ** ** p - jump a given number of position from start of file. ** ** If format is NULL, psf_binheader_readf returns the current offset. */ #if (CPU_IS_BIG_ENDIAN == 1) #define GET_MARKER(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \ ((ptr) [2] << 8) | ((ptr) [3]) ) #elif (CPU_IS_LITTLE_ENDIAN == 1) #define GET_MARKER(ptr) ( ((ptr) [0]) | ((ptr) [1] << 8) | \ ((ptr) [2] << 16) | ((ptr) [3] << 24) ) #else # error "Cannot determine endian-ness of processor." #endif #define GET_LE_SHORT(ptr) ( ((ptr) [1] << 8) | ((ptr) [0]) ) #define GET_BE_SHORT(ptr) ( ((ptr) [0] << 8) | ((ptr) [1]) ) #define GET_LE_3BYTE(ptr) ( ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]) ) #define GET_BE_3BYTE(ptr) ( ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]) ) #define GET_LE_INT(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \ ((ptr) [1] << 8) | ((ptr) [0]) ) #define GET_BE_INT(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \ ((ptr) [2] << 8) | ((ptr) [3]) ) #if (SIZEOF_LONG == 4) #define GET_LE_8BYTE(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \ ((ptr) [1] << 8) | ((ptr) [0]) ) #define GET_BE_8BYTE(ptr) ( ((ptr) [4] << 24) | ((ptr) [5] << 16) | \ ((ptr) [6] << 8) | ((ptr) [7]) ) #else #define GET_LE_8BYTE(ptr) ( (((ptr) [7] * 1L) << 56) | (((ptr) [6] * 1L) << 48) | \ (((ptr) [5] * 1L) << 40) | (((ptr) [4] * 1L) << 32) | \ (((ptr) [3] * 1L) << 24) | (((ptr) [2] * 1L) << 16) | \ (((ptr) [1] * 1L) << 8 ) | ((ptr) [0])) #define GET_BE_8BYTE(ptr) ( (((ptr) [0] * 1L) << 56) | (((ptr) [1] * 1L) << 48) | \ (((ptr) [2] * 1L) << 40) | (((ptr) [3] * 1L) << 32) | \ (((ptr) [4] * 1L) << 24) | (((ptr) [5] * 1L) << 16) | \ (((ptr) [6] * 1L) << 8 ) | ((ptr) [7])) #endif static int header_read (SF_PRIVATE *psf, void *ptr, int bytes) { int count = 0 ; if (psf->headindex + bytes > SIGNED_SIZEOF (psf->header)) { if (psf->headend < SIGNED_SIZEOF (psf->header)) psf_log_printf (psf, "Warning : Further header read would overflow buffer.\n") ; psf->headend = SIGNED_SIZEOF (psf->header) ; /* This is the best that we can do. */ return psf_fread (ptr, 1, bytes, psf) ; } ; if (psf->headindex + bytes > psf->headend) { count = psf_fread (psf->header + psf->headend, 1, bytes - (psf->headend - psf->headindex), psf) ; if (count != bytes - (int) (psf->headend - psf->headindex)) { psf_log_printf (psf, "Error : psf_fread returned short count.\n") ; return 0 ; } ; psf->headend += count ; } ; memcpy (ptr, psf->header + psf->headindex, bytes) ; psf->headindex += bytes ; return bytes ; } /* header_read */ static void header_seek (SF_PRIVATE *psf, sf_count_t position, int whence) { switch (whence) { case SEEK_SET : if (position > SIGNED_SIZEOF (psf->header)) { /* Too much header to cache so just seek instead. */ psf_fseek (psf, position, whence) ; return ; } ; if (position > psf->headend) psf->headend += psf_fread (psf->header + psf->headend, 1, position - psf->headend, psf) ; psf->headindex = position ; break ; case SEEK_CUR : if (psf->headindex + position < 0) break ; if (psf->headindex >= SIGNED_SIZEOF (psf->header)) { psf_fseek (psf, position, whence) ; return ; } ; if (psf->headindex + position <= psf->headend) { psf->headindex += position ; break ; } ; if (psf->headindex + position > SIGNED_SIZEOF (psf->header)) { /* Need to jump this without caching it. */ psf->headindex = psf->headend ; psf_fseek (psf, position, SEEK_CUR) ; break ; } ; psf->headend += psf_fread (psf->header + psf->headend, 1, position - (psf->headend - psf->headindex), psf) ; psf->headindex = psf->headend ; break ; case SEEK_END : default : psf_log_printf (psf, "Bad whence param in header_seek().\n") ; break ; } ; return ; } /* header_seek */ static int header_gets (SF_PRIVATE *psf, char *ptr, int bufsize) { int k ; for (k = 0 ; k < bufsize - 1 ; k++) { if (psf->headindex < psf->headend) { ptr [k] = psf->header [psf->headindex] ; psf->headindex ++ ; } else { psf->headend += psf_fread (psf->header + psf->headend, 1, 1, psf) ; ptr [k] = psf->header [psf->headindex] ; psf->headindex = psf->headend ; } ; if (ptr [k] == '\n') break ; } ; ptr [k] = 0 ; return k ; } /* header_gets */ int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) { va_list argptr ; sf_count_t *countptr, countdata ; unsigned char *ucptr, sixteen_bytes [16] ; unsigned int *intptr, intdata ; unsigned short *shortptr ; char *charptr ; float *floatptr ; double *doubleptr ; char c ; int byte_count = 0, count ; if (! format) return psf_ftell (psf) ; va_start (argptr, format) ; while ((c = *format++)) { switch (c) { case 'e' : /* All conversions are now from LE to host. */ psf->rwf_endian = SF_ENDIAN_LITTLE ; break ; case 'E' : /* All conversions are now from BE to host. */ psf->rwf_endian = SF_ENDIAN_BIG ; break ; case 'm' : intptr = va_arg (argptr, unsigned int*) ; ucptr = (unsigned char*) intptr ; byte_count += header_read (psf, ucptr, sizeof (int)) ; *intptr = GET_MARKER (ucptr) ; break ; case 'h' : intptr = va_arg (argptr, unsigned int*) ; ucptr = (unsigned char*) intptr ; byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ; { int k ; intdata = 0 ; for (k = 0 ; k < 16 ; k++) intdata ^= sixteen_bytes [k] << k ; } *intptr = intdata ; break ; case '1' : charptr = va_arg (argptr, char*) ; byte_count += header_read (psf, charptr, sizeof (char)) ; break ; case '2' : shortptr = va_arg (argptr, unsigned short*) ; ucptr = (unsigned char*) shortptr ; byte_count += header_read (psf, ucptr, sizeof (short)) ; if (psf->rwf_endian == SF_ENDIAN_BIG) *shortptr = GET_BE_SHORT (ucptr) ; else *shortptr = GET_LE_SHORT (ucptr) ; break ; case '3' : intptr = va_arg (argptr, unsigned int*) ; byte_count += header_read (psf, sixteen_bytes, 3) ; if (psf->rwf_endian == SF_ENDIAN_BIG) *intptr = GET_BE_3BYTE (sixteen_bytes) ; else *intptr = GET_LE_3BYTE (sixteen_bytes) ; break ; case '4' : intptr = va_arg (argptr, unsigned int*) ; ucptr = (unsigned char*) intptr ; byte_count += header_read (psf, ucptr, sizeof (int)) ; if (psf->rwf_endian == SF_ENDIAN_BIG) *intptr = GET_BE_INT (ucptr) ; else *intptr = GET_LE_INT (ucptr) ; break ; case '8' : countptr = va_arg (argptr, sf_count_t*) ; byte_count += header_read (psf, sixteen_bytes, 8) ; if (psf->rwf_endian == SF_ENDIAN_BIG) countdata = GET_BE_8BYTE (sixteen_bytes) ; else countdata = GET_LE_8BYTE (sixteen_bytes) ; *countptr = countdata ; break ; case 'f' : /* Float conversion */ floatptr = va_arg (argptr, float *) ; *floatptr = 0.0 ; byte_count += header_read (psf, floatptr, sizeof (float)) ; if (psf->rwf_endian == SF_ENDIAN_BIG) *floatptr = float32_be_read ((unsigned char*) floatptr) ; else *floatptr = float32_le_read ((unsigned char*) floatptr) ; break ; case 'd' : /* double conversion */ doubleptr = va_arg (argptr, double *) ; *doubleptr = 0.0 ; byte_count += header_read (psf, doubleptr, sizeof (double)) ; if (psf->rwf_endian == SF_ENDIAN_BIG) *doubleptr = double64_be_read ((unsigned char*) doubleptr) ; else *doubleptr = double64_le_read ((unsigned char*) doubleptr) ; break ; case 's' : psf_log_printf (psf, "Format conversion 's' not implemented yet.\n") ; /* strptr = va_arg (argptr, char *) ; size = strlen (strptr) + 1 ; size += (size & 1) ; longdata = H2LE_INT (size) ; get_int (psf, longdata) ; memcpy (&(psf->header [psf->headindex]), strptr, size) ; psf->headindex += size ; */ break ; case 'b' : charptr = va_arg (argptr, char*) ; count = va_arg (argptr, int) ; if (count > 0) byte_count += header_read (psf, charptr, count) ; break ; case 'G' : charptr = va_arg (argptr, char*) ; count = va_arg (argptr, int) ; if (count > 0) byte_count += header_gets (psf, charptr, count) ; break ; case 'z' : psf_log_printf (psf, "Format conversion 'z' not implemented yet.\n") ; /* size = va_arg (argptr, size_t) ; while (size) { psf->header [psf->headindex] = 0 ; psf->headindex ++ ; size -- ; } ; */ break ; case 'p' : /* Get the seek position first. */ count = va_arg (argptr, int) ; header_seek (psf, count, SEEK_SET) ; byte_count = count ; break ; case 'j' : /* Get the seek position first. */ count = va_arg (argptr, int) ; header_seek (psf, count, SEEK_CUR) ; byte_count += count ; break ; default : psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ; psf->error = SFE_INTERNAL ; break ; } ; } ; va_end (argptr) ; return byte_count ; } /* psf_binheader_readf */ /*----------------------------------------------------------------------------------------------- */ sf_count_t psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) { sf_count_t position, retval ; if (! (psf->blockwidth && psf->dataoffset >= 0)) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (! psf->sf.seekable) { psf->error = SFE_NOT_SEEKABLE ; return ((sf_count_t) -1) ; } ; position = psf->dataoffset + psf->blockwidth * samples_from_start ; if ((retval = psf_fseek (psf, position, SEEK_SET)) != position) { psf->error = SFE_SEEK_FAILED ; return ((sf_count_t) -1) ; } ; mode = mode ; return samples_from_start ; } /* psf_default_seek */ /*----------------------------------------------------------------------------------------------- */ void psf_hexdump (void *ptr, int len) { char ascii [17], *data ; int k, m ; if ((data = ptr) == NULL) return ; if (len <= 0) return ; puts ("") ; for (k = 0 ; k < len ; k += 16) { memset (ascii, ' ', sizeof (ascii)) ; printf ("%08X: ", k) ; for (m = 0 ; m < 16 && k + m < len ; m++) { printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ; ascii [m] = isprint (data [k + m]) ? data [k + m] : '.' ; } ; if (m <= 8) printf (" ") ; for ( ; m < 16 ; m++) printf (" ") ; ascii [16] = 0 ; printf (" %s\n", ascii) ; } ; puts ("") ; } /* psf_hexdump */ void psf_log_SF_INFO (SF_PRIVATE *psf) { psf_log_printf (psf, "---------------------------------\n") ; psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ; psf_log_printf (psf, " Frames : %C\n", psf->sf.frames) ; psf_log_printf (psf, " Channels : %d\n", psf->sf.channels) ; psf_log_printf (psf, " Format : 0x%X\n", psf->sf.format) ; psf_log_printf (psf, " Sections : %d\n", psf->sf.sections) ; psf_log_printf (psf, " Seekable : %s\n", psf->sf.seekable ? "TRUE" : "FALSE") ; psf_log_printf (psf, "---------------------------------\n") ; } /* psf_dump_SFINFO */ /*======================================================================================== */ void* psf_memset (void *s, int c, sf_count_t len) { char *ptr ; int setcount ; ptr = (char *) s ; while (len > 0) { setcount = (len > 0x10000000) ? 0x10000000 : (int) len ; memset (ptr, c, setcount) ; ptr += setcount ; len -= setcount ; } ; return s ; } /* psf_memset */ void psf_get_date_str (char *str, int maxlen) { time_t current ; struct tm timedata, *tmptr ; time (¤t) ; #if defined (HAVE_GMTIME_R) /* If the re-entrant version is available, use it. */ tmptr = gmtime_r (¤t, &timedata) ; #elif defined (HAVE_GMTIME) /* Otherwise use the standard one and copy the data to local storage. */ tmptr = gmtime (¤t) ; memcpy (&timedata, tmptr, sizeof (timedata)) ; #else tmptr = NULL ; #endif if (tmptr) LSF_SNPRINTF (str, maxlen, "%4d-%02d-%02d %02d:%02d:%02d UTC", 1900 + timedata.tm_year, timedata.tm_mon, timedata.tm_mday, timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ; else LSF_SNPRINTF (str, maxlen, "Unknown date") ; return ; } /* psf_get_date_str */ int subformat_to_bytewidth (int format) { switch (format) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_S8 : return 1 ; case SF_FORMAT_PCM_16 : return 2 ; case SF_FORMAT_PCM_24 : return 3 ; case SF_FORMAT_PCM_32 : case SF_FORMAT_FLOAT : return 4 ; case SF_FORMAT_DOUBLE : return 8 ; } ; return 0 ; } /* subformat_to_bytewidth */ int s_bitwidth_to_subformat (int bits) { static int array [] = { SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32 } ; if (bits < 8 || bits > 32) return 0 ; return array [((bits + 7) / 8) - 1] ; } /* bitwidth_to_subformat */ int u_bitwidth_to_subformat (int bits) { static int array [] = { SF_FORMAT_PCM_U8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32 } ; if (bits < 8 || bits > 32) return 0 ; return array [((bits + 7) / 8) - 1] ; } /* bitwidth_to_subformat */ #endif /* PSF_LOG_PRINTF_ONLY */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 33e9795e-f717-461a-9feb-65d083a56395 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include /* * 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER */ static void Postprocessing ( struct gsm_state * S, register word * s) { register int k; register word msr = S->msr; register word tmp; for (k = 160; k--; s++) { tmp = GSM_MULT_R( msr, 28180 ); msr = GSM_ADD(*s, tmp); /* Deemphasis */ *s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */ } S->msr = msr; } void Gsm_Decoder ( struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s) /* [0..159] OUT */ { int j, k; word erp[40], wt[160]; word * drp = S->dp0 + 120; for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) { Gsm_RPE_Decoding( /*-S,-*/ *xmaxcr, *Mcr, xMcr, erp ); Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp ); for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ]; } Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s ); Postprocessing(S, s); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 11ae5b90-2e8b-400b-ac64-a69a1fc6cc41 */ /* ** Copyright (C) 2003,2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include /*============================================================================ ** Rule number 1 is to only apply dither when going from a larger bitwidth ** to a smaller bitwidth. This can happen on both read and write. ** ** Need to apply dither on all conversions marked X below. ** ** Dither on write: ** ** Input ** | short int float double ** --------+----------------------------------------------- ** O 8 bit | X X X X ** u 16 bit | none X X X ** t 24 bit | none X X X ** p 32 bit | none none X X ** u float | none none none none ** t double | none none none none ** ** Dither on read: ** ** Input ** O | 8 bit 16 bit 24 bit 32 bit float double ** u --------+------------------------------------------------- ** t short | none none X X X X ** p int | none none none X X X ** u float | none none none none none none ** t double | none none none none none none */ #define SFE_DITHER_BAD_PTR 666 #define SFE_DITHER_BAD_TYPE 667 typedef struct { int read_short_dither_bits, read_int_dither_bits ; int write_short_dither_bits, write_int_dither_bits ; double read_float_dither_scale, read_double_dither_bits ; double write_float_dither_scale, write_double_dither_bits ; sf_count_t (*read_short) (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; sf_count_t (*read_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; sf_count_t (*read_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; sf_count_t (*read_double) (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; sf_count_t (*write_short) (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; sf_count_t (*write_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; sf_count_t (*write_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; sf_count_t (*write_double) (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; double buffer [SF_BUFFER_LEN / sizeof (double)] ; } DITHER_DATA ; static sf_count_t dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dither_write_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dither_write_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dither_write_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dither_write_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; int dither_init (SF_PRIVATE *psf, int mode) { DITHER_DATA *pdither ; pdither = psf->dither ; /* This may be NULL. */ /* Turn off dither on read. */ if (mode == SFM_READ && psf->read_dither.type == SFD_NO_DITHER) { if (pdither == NULL) return 0 ; /* Dither is already off, so just return. */ if (pdither->read_short) psf->read_short = pdither->read_short ; if (pdither->read_int) psf->read_int = pdither->read_int ; if (pdither->read_float) psf->read_float = pdither->read_float ; if (pdither->read_double) psf->read_double = pdither->read_double ; return 0 ; } ; /* Turn off dither on write. */ if (mode == SFM_WRITE && psf->write_dither.type == SFD_NO_DITHER) { if (pdither == NULL) return 0 ; /* Dither is already off, so just return. */ if (pdither->write_short) psf->write_short = pdither->write_short ; if (pdither->write_int) psf->write_int = pdither->write_int ; if (pdither->write_float) psf->write_float = pdither->write_float ; if (pdither->write_double) psf->write_double = pdither->write_double ; return 0 ; } ; /* Turn on dither on read if asked. */ if (mode == SFM_READ && psf->read_dither.type != 0) { if (pdither == NULL) pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ; if (pdither == NULL) return SFE_MALLOC_FAILED ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_DOUBLE : case SF_FORMAT_FLOAT : pdither->read_int = psf->read_int ; psf->read_int = dither_read_int ; case SF_FORMAT_PCM_32 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : pdither->read_short = psf->read_short ; psf->read_short = dither_read_short ; default : break ; } ; } ; /* Turn on dither on write if asked. */ if (mode == SFM_WRITE && psf->write_dither.type != 0) { if (pdither == NULL) pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ; if (pdither == NULL) return SFE_MALLOC_FAILED ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_DOUBLE : case SF_FORMAT_FLOAT : pdither->write_int = psf->write_int ; psf->write_int = dither_write_int ; case SF_FORMAT_PCM_32 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : default : break ; } ; pdither->write_short = psf->write_short ; psf->write_short = dither_write_short ; pdither->write_int = psf->write_int ; psf->write_int = dither_write_int ; pdither->write_float = psf->write_float ; psf->write_float = dither_write_float ; pdither->write_double = psf->write_double ; psf->write_double = dither_write_double ; } ; return 0 ; } /* dither_init */ /*============================================================================== */ static void dither_short (const short *in, short *out, int frames, int channels) ; static void dither_int (const int *in, int *out, int frames, int channels) ; static void dither_float (const float *in, float *out, int frames, int channels) ; static void dither_double (const double *in, double *out, int frames, int channels) ; static sf_count_t dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) { psf = psf ; ptr = ptr ; return len ; } /* dither_read_short */ static sf_count_t dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) { psf = psf ; ptr = ptr ; return len ; } /* dither_read_int */ /*------------------------------------------------------------------------------ */ static sf_count_t dither_write_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) { DITHER_DATA *pdither ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pdither = psf->dither) == NULL) { psf->error = SFE_DITHER_BAD_PTR ; return 0 ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : case SF_FORMAT_DPCM_8 : break ; default : return pdither->write_short (psf, ptr, len) ; } ; bufferlen = sizeof (pdither->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dither_write_short */ static sf_count_t dither_write_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) { DITHER_DATA *pdither ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pdither = psf->dither) == NULL) { psf->error = SFE_DITHER_BAD_PTR ; return 0 ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_DPCM_8 : case SF_FORMAT_DPCM_16 : break ; default : return pdither->write_int (psf, ptr, len) ; } ; bufferlen = sizeof (pdither->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dither_write_int */ static sf_count_t dither_write_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) { DITHER_DATA *pdither ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pdither = psf->dither) == NULL) { psf->error = SFE_DITHER_BAD_PTR ; return 0 ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_DPCM_8 : case SF_FORMAT_DPCM_16 : break ; default : return pdither->write_float (psf, ptr, len) ; } ; bufferlen = sizeof (pdither->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (float) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dither_write_float */ static sf_count_t dither_write_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) { DITHER_DATA *pdither ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pdither = psf->dither) == NULL) { psf->error = SFE_DITHER_BAD_PTR ; return 0 ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_DPCM_8 : case SF_FORMAT_DPCM_16 : break ; default : return pdither->write_double (psf, ptr, len) ; } ; bufferlen = sizeof (pdither->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (double) len ; writecount /= psf->sf.channels ; writecount *= psf->sf.channels ; dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ; thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dither_write_double */ /*============================================================================== */ static void dither_short (const short *in, short *out, int frames, int channels) { int ch, k ; for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; } /* dither_short */ static void dither_int (const int *in, int *out, int frames, int channels) { int ch, k ; for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; } /* dither_int */ static void dither_float (const float *in, float *out, int frames, int channels) { int ch, k ; for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; } /* dither_float */ static void dither_double (const double *in, double *out, int frames, int channels) { int ch, k ; for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; } /* dither_double */ /*============================================================================== */ #if 0 /* ** Not made public because this (maybe) requires storage of state information. ** ** Also maybe need separate state info for each channel!!!! */ int DO_NOT_USE_sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int frames, int channels) { int ch, k ; if (! dither) return SFE_DITHER_BAD_PTR ; switch (dither->type & SFD_TYPEMASK) { case SFD_WHITE : case SFD_TRIANGULAR_PDF : for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; break ; default : return SFE_DITHER_BAD_TYPE ; } ; return 0 ; } /* DO_NOT_USE_sf_dither_short */ int DO_NOT_USE_sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int frames, int channels) { int ch, k ; if (! dither) return SFE_DITHER_BAD_PTR ; switch (dither->type & SFD_TYPEMASK) { case SFD_WHITE : case SFD_TRIANGULAR_PDF : for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; break ; default : return SFE_DITHER_BAD_TYPE ; } ; return 0 ; } /* DO_NOT_USE_sf_dither_int */ int DO_NOT_USE_sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int frames, int channels) { int ch, k ; if (! dither) return SFE_DITHER_BAD_PTR ; switch (dither->type & SFD_TYPEMASK) { case SFD_WHITE : case SFD_TRIANGULAR_PDF : for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; break ; default : return SFE_DITHER_BAD_TYPE ; } ; return 0 ; } /* DO_NOT_USE_sf_dither_float */ int DO_NOT_USE_sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int frames, int channels) { int ch, k ; if (! dither) return SFE_DITHER_BAD_PTR ; switch (dither->type & SFD_TYPEMASK) { case SFD_WHITE : case SFD_TRIANGULAR_PDF : for (ch = 0 ; ch < channels ; ch++) for (k = ch ; k < channels * frames ; k += channels) out [k] = in [k] ; break ; default : return SFE_DITHER_BAD_TYPE ; } ; return 0 ; } /* DO_NOT_USE_sf_dither_double */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 673fad58-5314-421c-9144-9d54bfdf104c */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #if CPU_IS_LITTLE_ENDIAN #define DOUBLE64_READ double64_le_read #define DOUBLE64_WRITE double64_le_write #elif CPU_IS_BIG_ENDIAN #define DOUBLE64_READ double64_be_read #define DOUBLE64_WRITE double64_be_write #endif /*-------------------------------------------------------------------------------------------- ** Processor floating point capabilities. double64_get_capability () returns one of the ** latter three values. */ enum { DOUBLE_UNKNOWN = 0x00, DOUBLE_CAN_RW_LE = 0x23, DOUBLE_CAN_RW_BE = 0x34, DOUBLE_BROKEN_LE = 0x45, DOUBLE_BROKEN_BE = 0x56 } ; /*-------------------------------------------------------------------------------------------- ** Prototypes for private functions. */ static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t host_write_s2d (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t host_write_i2d (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t host_write_f2d (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t host_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void d2s_array (double *buffer, unsigned int count, short *ptr) ; static void d2i_array (double *buffer, unsigned int count, int *ptr) ; static void double64d2f_array (double *buffer, unsigned int count, float *ptr) ; static void s2d_array (short *ptr, double *buffer, unsigned int count) ; static void i2d_array (int *ptr, double *buffer, unsigned int count) ; static void double64f2d_array (float *ptr, double *buffer, unsigned int count) ; static void double64_peak_update (SF_PRIVATE *psf, double *buffer, int count, int indx) ; static int double64_get_capability (SF_PRIVATE *psf) ; static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t replace_write_s2d (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t replace_write_i2d (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t replace_write_f2d (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t replace_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void d2bd_read (double *buffer, int count) ; static void bd2d_write (double *buffer, int count) ; /*-------------------------------------------------------------------------------------------- ** Exported functions. */ int double64_init (SF_PRIVATE *psf) { static int double64_caps ; double64_caps = double64_get_capability (psf) ; psf->blockwidth = sizeof (double) * psf->sf.channels ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { switch (psf->endian + double64_caps) { case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : psf->float_endswap = SF_FALSE ; psf->read_short = host_read_d2s ; psf->read_int = host_read_d2i ; psf->read_float = host_read_d2f ; psf->read_double = host_read_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : psf->float_endswap = SF_FALSE ; psf->read_short = host_read_d2s ; psf->read_int = host_read_d2i ; psf->read_float = host_read_d2f ; psf->read_double = host_read_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : psf->float_endswap = SF_TRUE ; psf->read_short = host_read_d2s ; psf->read_int = host_read_d2i ; psf->read_float = host_read_d2f ; psf->read_double = host_read_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : psf->float_endswap = SF_TRUE ; psf->read_short = host_read_d2s ; psf->read_int = host_read_d2i ; psf->read_float = host_read_d2f ; psf->read_double = host_read_d ; break ; /* When the CPU is not IEEE compatible. */ case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : psf->float_endswap = SF_FALSE ; psf->read_short = replace_read_d2s ; psf->read_int = replace_read_d2i ; psf->read_float = replace_read_d2f ; psf->read_double = replace_read_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : psf->float_endswap = SF_FALSE ; psf->read_short = replace_read_d2s ; psf->read_int = replace_read_d2i ; psf->read_float = replace_read_d2f ; psf->read_double = replace_read_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : psf->float_endswap = SF_TRUE ; psf->read_short = replace_read_d2s ; psf->read_int = replace_read_d2i ; psf->read_float = replace_read_d2f ; psf->read_double = replace_read_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : psf->float_endswap = SF_TRUE ; psf->read_short = replace_read_d2s ; psf->read_int = replace_read_d2i ; psf->read_float = replace_read_d2f ; psf->read_double = replace_read_d ; break ; default : break ; } ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { switch (psf->endian + double64_caps) { case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : psf->float_endswap = SF_FALSE ; psf->write_short = host_write_s2d ; psf->write_int = host_write_i2d ; psf->write_float = host_write_f2d ; psf->write_double = host_write_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : psf->float_endswap = SF_FALSE ; psf->write_short = host_write_s2d ; psf->write_int = host_write_i2d ; psf->write_float = host_write_f2d ; psf->write_double = host_write_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : psf->float_endswap = SF_TRUE ; psf->write_short = host_write_s2d ; psf->write_int = host_write_i2d ; psf->write_float = host_write_f2d ; psf->write_double = host_write_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : psf->float_endswap = SF_TRUE ; psf->write_short = host_write_s2d ; psf->write_int = host_write_i2d ; psf->write_float = host_write_f2d ; psf->write_double = host_write_d ; break ; /* When the CPU is not IEEE compatible. */ case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : psf->float_endswap = SF_FALSE ; psf->write_short = replace_write_s2d ; psf->write_int = replace_write_i2d ; psf->write_float = replace_write_f2d ; psf->write_double = replace_write_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : psf->float_endswap = SF_FALSE ; psf->write_short = replace_write_s2d ; psf->write_int = replace_write_i2d ; psf->write_float = replace_write_f2d ; psf->write_double = replace_write_d ; break ; case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : psf->float_endswap = SF_TRUE ; psf->write_short = replace_write_s2d ; psf->write_int = replace_write_i2d ; psf->write_float = replace_write_f2d ; psf->write_double = replace_write_d ; break ; case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : psf->float_endswap = SF_TRUE ; psf->write_short = replace_write_s2d ; psf->write_int = replace_write_i2d ; psf->write_float = replace_write_f2d ; psf->write_double = replace_write_d ; break ; default : break ; } ; } ; if (psf->filelength > psf->dataoffset) { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; } else psf->datalength = 0 ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* double64_init */ /*---------------------------------------------------------------------------- ** From : http://www.hpcf.cam.ac.uk/fp_formats.html ** ** 64 bit double precision layout (big endian) ** Sign bit 0 ** Exponent bits 1-11 ** Mantissa bits 12-63 ** Exponent Offset 1023 ** ** double single ** ** +INF 7FF0000000000000 7F800000 ** -INF FFF0000000000000 FF800000 ** NaN 7FF0000000000001 7F800001 ** to to ** 7FFFFFFFFFFFFFFF 7FFFFFFF ** and and ** FFF0000000000001 FF800001 ** to to ** FFFFFFFFFFFFFFFF FFFFFFFF ** +OVER 7FEFFFFFFFFFFFFF 7F7FFFFF ** -OVER FFEFFFFFFFFFFFFF FF7FFFFF ** +UNDER 0010000000000000 00800000 ** -UNDER 8010000000000000 80800000 */ double double64_be_read (unsigned char *cptr) { int exponent, negative ; double dvalue ; negative = (cptr [0] & 0x80) ? 1 : 0 ; exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ; /* Might not have a 64 bit long, so load the mantissa into a double. */ dvalue = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ; dvalue += ((cptr [5] << 16) | (cptr [6] << 8) | cptr [7]) / ((double) 0x1000000) ; if (exponent == 0 && dvalue == 0.0) return 0.0 ; dvalue += 0x10000000 ; exponent = exponent - 0x3FF ; dvalue = dvalue / ((double) 0x10000000) ; if (negative) dvalue *= -1 ; if (exponent > 0) dvalue *= (1 << exponent) ; else if (exponent < 0) dvalue /= (1 << abs (exponent)) ; return dvalue ; } /* double64_be_read */ double double64_le_read (unsigned char *cptr) { int exponent, negative ; double dvalue ; negative = (cptr [7] & 0x80) ? 1 : 0 ; exponent = ((cptr [7] & 0x7F) << 4) | ((cptr [6] >> 4) & 0xF) ; /* Might not have a 64 bit long, so load the mantissa into a double. */ dvalue = (((cptr [6] & 0xF) << 24) | (cptr [5] << 16) | (cptr [4] << 8) | cptr [3]) ; dvalue += ((cptr [2] << 16) | (cptr [1] << 8) | cptr [0]) / ((double) 0x1000000) ; if (exponent == 0 && dvalue == 0.0) return 0.0 ; dvalue += 0x10000000 ; exponent = exponent - 0x3FF ; dvalue = dvalue / ((double) 0x10000000) ; if (negative) dvalue *= -1 ; if (exponent > 0) dvalue *= (1 << exponent) ; else if (exponent < 0) dvalue /= (1 << abs (exponent)) ; return dvalue ; } /* double64_le_read */ void double64_be_write (double in, unsigned char *out) { int exponent, mantissa ; memset (out, 0, sizeof (double)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; out [0] |= 0x80 ; } ; in = frexp (in, &exponent) ; exponent += 1022 ; out [0] |= (exponent >> 4) & 0x7F ; out [1] |= (exponent << 4) & 0xF0 ; in *= 0x20000000 ; mantissa = lrint (floor (in)) ; out [1] |= (mantissa >> 24) & 0xF ; out [2] = (mantissa >> 16) & 0xFF ; out [3] = (mantissa >> 8) & 0xFF ; out [4] = mantissa & 0xFF ; in = fmod (in, 1.0) ; in *= 0x1000000 ; mantissa = lrint (floor (in)) ; out [5] = (mantissa >> 16) & 0xFF ; out [6] = (mantissa >> 8) & 0xFF ; out [7] = mantissa & 0xFF ; return ; } /* double64_be_write */ void double64_le_write (double in, unsigned char *out) { int exponent, mantissa ; memset (out, 0, sizeof (double)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; out [7] |= 0x80 ; } ; in = frexp (in, &exponent) ; exponent += 1022 ; out [7] |= (exponent >> 4) & 0x7F ; out [6] |= (exponent << 4) & 0xF0 ; in *= 0x20000000 ; mantissa = lrint (floor (in)) ; out [6] |= (mantissa >> 24) & 0xF ; out [5] = (mantissa >> 16) & 0xFF ; out [4] = (mantissa >> 8) & 0xFF ; out [3] = mantissa & 0xFF ; in = fmod (in, 1.0) ; in *= 0x1000000 ; mantissa = lrint (floor (in)) ; out [2] = (mantissa >> 16) & 0xFF ; out [1] = (mantissa >> 8) & 0xFF ; out [0] = mantissa & 0xFF ; return ; } /* double64_le_write */ /*============================================================================================== ** Private functions. */ static void double64_peak_update (SF_PRIVATE *psf, double *buffer, int count, int indx) { int chan ; int k, position ; float fmaxval ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { fmaxval = fabs (buffer [chan]) ; position = 0 ; for (k = chan ; k < count ; k += psf->sf.channels) if (fmaxval < fabs (buffer [k])) { fmaxval = fabs (buffer [k]) ; position = k ; } ; if (fmaxval > psf->pchunk->peaks [chan].value) { psf->pchunk->peaks [chan].value = fmaxval ; psf->pchunk->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ; } ; } ; return ; } /* double64_peak_update */ static int double64_get_capability (SF_PRIVATE *psf) { union { double d ; int i [2] ; unsigned char c [8] ; } data ; data.d = 1.234567890123456789 ; /* Some abitrary value. */ if (! psf->ieee_replace) { /* If this test is true ints and floats are compatible and little endian. */ if (data.i [0] == 0x428c59fb && data.i [1] == 0x3ff3c0ca && data.c [0] == 0xfb && data.c [2] == 0x8c && data.c [4] == 0xca && data.c [6] == 0xf3) return DOUBLE_CAN_RW_LE ; /* If this test is true ints and floats are compatible and big endian. */ if ((data.i [0] == 0x3ff3c0ca && data.i [1] == 0x428c59fb) && (data.c [0] == 0x3f && data.c [2] == 0xc0 && data.c [4] == 0x42 && data.c [6] == 0x59)) return DOUBLE_CAN_RW_BE ; } ; /* Doubles are broken. Don't expect reading or writing to be fast. */ psf_log_printf (psf, "Using IEEE replacement code for double.\n") ; return (CPU_IS_LITTLE_ENDIAN) ? DOUBLE_BROKEN_LE : DOUBLE_BROKEN_BE ; } /* double64_get_capability */ /*---------------------------------------------------------------------------------------------- */ static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, readcount) ; d2s_array ((double*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* host_read_d2s */ static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, readcount) ; d2i_array ((double*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* host_read_d2i */ static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, readcount) ; double64d2f_array ((double*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* host_read_d2f */ static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if (psf->float_endswap != SF_TRUE) return psf_fread (ptr, sizeof (double), len, psf) ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; endswap_long_copy ((long*) (ptr + total), (long*) psf->buffer, thisread) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* host_read_d */ static sf_count_t host_write_s2d (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2d_array (ptr + total, (double*) (psf->buffer), writecount) ; if (psf->has_peak) double64_peak_update (psf, (double*) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* host_write_s2d */ static sf_count_t host_write_i2d (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2d_array (ptr + total, (double*) (psf->buffer), writecount) ; if (psf->has_peak) double64_peak_update (psf, (double*) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* host_write_i2d */ static sf_count_t host_write_f2d (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; double64f2d_array (ptr + total, (double*) (psf->buffer), writecount) ; if (psf->has_peak) double64_peak_update (psf, (double*) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* host_write_f2d */ static sf_count_t host_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if (psf->has_peak) double64_peak_update (psf, ptr, len, 0) ; if (psf->float_endswap != SF_TRUE) return psf_fwrite (ptr, sizeof (double), len, psf) ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_long_copy ((long*) psf->buffer, (long*) (ptr + total), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* host_write_d */ /*======================================================================================= */ static void d2s_array (double *src, unsigned int count, short *dest) { while (count) { count -- ; dest [count] = lrint (src [count]) ; } ; } /* d2s_array */ static void d2i_array (double *src, unsigned int count, int *dest) { while (count) { count -- ; dest [count] = lrint (src [count]) ; } ; } /* d2i_array */ static void double64d2f_array (double *src, unsigned int count, float *dest) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* double64d2f_array */ static void s2d_array (short *src, double *dest, unsigned int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* s2d_array */ static void i2d_array (int *src, double *dest, unsigned int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* i2d_array */ static void double64f2d_array (float *src, double *dest, unsigned int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* double64f2d_array */ /*======================================================================================= */ static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, readcount) ; d2bd_read ((double *) (psf->buffer), readcount) ; d2s_array ((double*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_d2s */ static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, readcount) ; d2bd_read ((double *) (psf->buffer), readcount) ; d2i_array ((double*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_d2i */ static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long *) psf->buffer, readcount) ; d2bd_read ((double *) (psf->buffer), readcount) ; memcpy (ptr + total, psf->buffer, readcount * sizeof (double)) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_d2f */ static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; /* FIXME : This is probably nowhere near optimal. */ bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (double), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, thisread) ; d2bd_read ((double *) (psf->buffer), thisread) ; memcpy (ptr + total, psf->buffer, thisread * sizeof (double)) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_d */ static sf_count_t replace_write_s2d (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2d_array (ptr + total, (double *) (psf->buffer), writecount) ; if (psf->has_peak) double64_peak_update (psf, (double *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; bd2d_write ((double *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_s2d */ static sf_count_t replace_write_i2d (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2d_array (ptr + total, (double*) (psf->buffer), writecount) ; if (psf->has_peak) double64_peak_update (psf, (double *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; bd2d_write ((double *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_i2d */ static sf_count_t replace_write_f2d (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; double64f2d_array (ptr + total, (double*) (psf->buffer), writecount) ; bd2d_write ((double *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_f2d */ static sf_count_t replace_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; /* FIXME : This is probably nowhere near optimal. */ if (psf->has_peak) double64_peak_update (psf, ptr, len, 0) ; bufferlen = sizeof (psf->buffer) / sizeof (double) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; memcpy (psf->buffer, ptr + total, writecount * sizeof (double)) ; bd2d_write ((double *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_long_array ((long*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (double), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_d */ /*---------------------------------------------------------------------------------------------- */ static void d2bd_read (double *buffer, int count) { while (count) { count -- ; buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ; } ; } /* d2bd_read */ static void bd2d_write (double *buffer, int count) { while (count) { count -- ; DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; } ; } /* bd2d_write */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 4ee243b7-8c7a-469b-869c-e9aa0ee3b77f */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int dwd_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* dwd_open */ #else /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define SFE_DWD_NO_DWD 1666 #define SFE_DWD_BAND_BIT_WIDTH 1667 #define SFE_DWD_COMPRESSION 1668 #define DWD_IDENTIFIER "DiamondWare Digitized\n\0\x1a" #define DWD_IDENTIFIER_LEN 24 #define DWD_HEADER_LEN 57 /*------------------------------------------------------------------------------ ** Typedefs. */ /*------------------------------------------------------------------------------ ** Private static functions. */ static int dwd_read_header (SF_PRIVATE *psf) ; static int dwd_close (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int dwd_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = dwd_read_header (psf))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_DWD) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { /*-psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU) psf->endian = SF_ENDIAN_LITTLE ; else if (psf->endian != SF_ENDIAN_LITTLE) psf->endian = SF_ENDIAN_BIG ; if (! (encoding = dwd_write_header (psf, SF_FALSE))) return psf->error ; psf->write_header = dwd_write_header ; -*/ } ; psf->close = dwd_close ; /*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/ return error ; } /* dwd_open */ /*------------------------------------------------------------------------------ */ static int dwd_close (SF_PRIVATE *psf) { psf = psf ; return 0 ; } /* dwd_close */ /* This struct contains all the fields of interest om the DWD header, but does not ** do so in the same order and layout as the actual file, header. ** No assumptions are made about the packing of this struct. */ typedef struct { unsigned char major, minor, compression, channels, bitwidth ; unsigned short srate, maxval ; unsigned int id, datalen, frames, offset ; } DWD_HEADER ; static int dwd_read_header (SF_PRIVATE *psf) { DWD_HEADER dwdh ; memset (psf->buffer, 0, sizeof (psf->buffer)) ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pb", 0, psf->buffer, DWD_IDENTIFIER_LEN) ; if (memcmp (psf->buffer, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0) return SFE_DWD_NO_DWD ; psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", psf->buffer) ; psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ; psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ; psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ; psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ; psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ; psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n", dwdh.major, dwdh.minor, dwdh.id) ; psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ; if (dwdh.compression != 0) { psf_log_printf (psf, "Unsupported compression\n") ; return SFE_DWD_COMPRESSION ; } else psf_log_printf (psf, "None\n") ; psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n" " Bit Width : %d\n", dwdh.srate, dwdh.channels, dwdh.bitwidth) ; switch (dwdh.bitwidth) { case 8 : psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case 16 : psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ; return SFE_DWD_BAND_BIT_WIDTH ; } ; if (psf->filelength != dwdh.offset + dwdh.datalen) { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ; } else psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ; psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ; psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ; psf->datalength = dwdh.datalen ; psf->dataoffset = dwdh.offset ; psf->endian = SF_ENDIAN_LITTLE ; psf->sf.samplerate = dwdh.srate ; psf->sf.channels = dwdh.channels ; psf->sf.sections = 1 ; return pcm_init (psf) ; } /* dwd_read_header */ /*------------------------------------------------------------------------------ */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: a5e1d2a6-a840-4039-a0e7-e1a43eb05a4f */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*=========================================================================== ** Delta Word Variable Width ** ** This decoder and encoder were implemented using information found in this ** document : http://home.swbell.net/rubywand/R011SNDFMTS.TXT ** ** According to the document, the algorithm "was invented 1991 by Magnus ** Lidstrom and is copyright 1993 by NuEdge Development". */ #include #include #include typedef struct { int dwm_maxsize, bit_width, max_delta, span ; int samplecount ; int bit_count, bits, last_delta_width, last_sample ; struct { int index, end ; unsigned char buffer [256] ; } b ; } DWVW_PRIVATE ; /*============================================================================================ */ static sf_count_t dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t dwvw_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dwvw_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dwvw_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dwvw_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int dwvw_close (SF_PRIVATE *psf) ; static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ; static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) ; static int dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ; static void dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) ; static void dwvw_read_reset (DWVW_PRIVATE *pdwvw) ; /*============================================================================================ ** DWVW initialisation function. */ int dwvw_init (SF_PRIVATE *psf, int bitwidth) { DWVW_PRIVATE *pdwvw ; if (bitwidth > 24) return SFE_DWVW_BAD_BITWIDTH ; if (psf->mode == SFM_RDWR) return SFE_BAD_MODE_RW ; if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pdwvw ; pdwvw->bit_width = bitwidth ; pdwvw->dwm_maxsize = bitwidth / 2 ; pdwvw->max_delta = 1 << (bitwidth - 1) ; pdwvw->span = 1 << bitwidth ; dwvw_read_reset (pdwvw) ; if (psf->mode == SFM_READ) { psf->read_short = dwvw_read_s ; psf->read_int = dwvw_read_i ; psf->read_float = dwvw_read_f ; psf->read_double = dwvw_read_d ; } ; if (psf->mode == SFM_WRITE) { psf->write_short = dwvw_write_s ; psf->write_int = dwvw_write_i ; psf->write_float = dwvw_write_f ; psf->write_double = dwvw_write_d ; } ; psf->seek = dwvw_seek ; psf->close = dwvw_close ; /* FIXME : This s bogus. */ psf->sf.frames = SF_COUNT_MAX ; psf->datalength = psf->sf.frames ; /* EMXIF : This s bogus. */ return 0 ; } /* dwvw_init */ /*-------------------------------------------------------------------------------------------- */ static int dwvw_close (SF_PRIVATE *psf) { DWVW_PRIVATE *pdwvw ; if (psf->fdata == NULL) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE) { static int last_values [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ; /* Write 8 zero samples to fully flush output. */ dwvw_encode_data (psf, pdwvw, last_values, 12) ; /* Write the last buffer worth of data to disk. */ psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; } ; return 0 ; } /* dwvw_close */ static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { DWVW_PRIVATE *pdwvw ; mode = mode ; if (! psf->fdata) { psf->error = SFE_INTERNAL ; return ((sf_count_t) -1) ; } ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; if (offset == 0) { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; dwvw_read_reset (pdwvw) ; return 0 ; } ; psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } /* dwvw_seek */ /*============================================================================== */ static sf_count_t dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* dwvw_read_s */ static sf_count_t dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = dwvw_decode_data (psf, pdwvw, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* dwvw_read_i */ static sf_count_t dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (float) (iptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* dwvw_read_f */ static sf_count_t dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (iptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* dwvw_read_d */ static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) { int count ; int delta_width_modifier, delta_width, delta_negative, delta, sample ; /* Restore state from last decode call. */ delta_width = pdwvw->last_delta_width ; sample = pdwvw->last_sample ; for (count = 0 ; count < len ; count++) { /* If bit_count parameter is zero get the delta_width_modifier. */ delta_width_modifier = dwvw_decode_load_bits (psf, pdwvw, -1) ; /* Check for end of input bit stream. Break loop if end. */ if (delta_width_modifier < 0) break ; if (delta_width_modifier && dwvw_decode_load_bits (psf, pdwvw, 1)) delta_width_modifier = - delta_width_modifier ; /* Calculate the current word width. */ delta_width = (delta_width + delta_width_modifier + pdwvw->bit_width) % pdwvw->bit_width ; /* Load the delta. */ delta = 0 ; if (delta_width) { delta = dwvw_decode_load_bits (psf, pdwvw, delta_width - 1) | (1 << (delta_width - 1)) ; delta_negative = dwvw_decode_load_bits (psf, pdwvw, 1) ; if (delta == pdwvw->max_delta - 1) delta += dwvw_decode_load_bits (psf, pdwvw, 1) ; if (delta_negative) delta = -delta ; } ; /* Calculate the sample */ sample += delta ; if (sample >= pdwvw->max_delta) sample -= pdwvw->span ; else if (sample < - pdwvw->max_delta) sample += pdwvw->span ; /* Store the sample justifying to the most significant bit. */ ptr [count] = sample << (32 - pdwvw->bit_width) ; if (pdwvw->b.end == 0 && pdwvw->bit_count == 0) break ; } ; pdwvw->last_delta_width = delta_width ; pdwvw->last_sample = sample ; pdwvw->samplecount += count ; return count ; } /* dwvw_decode_data */ static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) { int output = 0, get_dwm = SF_FALSE ; /* ** Depending on the value of parameter bit_count, either get the ** required number of bits (ie bit_count > 0) or the ** delta_width_modifier (otherwise). */ if (bit_count < 0) { get_dwm = SF_TRUE ; /* modify bit_count to ensure we have enought bits for finding dwm. */ bit_count = pdwvw->dwm_maxsize ; } ; /* Load bits in bit reseviour. */ while (pdwvw->bit_count < bit_count) { if (pdwvw->b.index >= pdwvw->b.end) { pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ; pdwvw->b.index = 0 ; } ; /* Check for end of input stream. */ if (bit_count < 8 && pdwvw->b.end == 0) return -1 ; pdwvw->bits = (pdwvw->bits << 8) ; if (pdwvw->b.index < pdwvw->b.end) { pdwvw->bits |= pdwvw->b.buffer [pdwvw->b.index] ; pdwvw->b.index ++ ; } ; pdwvw->bit_count += 8 ; } ; /* If asked to get bits do so. */ if (! get_dwm) { output = (pdwvw->bits >> (pdwvw->bit_count - bit_count)) & ((1 << bit_count) - 1) ; pdwvw->bit_count -= bit_count ; return output ; } ; /* Otherwise must have been asked to get delta_width_modifier. */ while (output < (pdwvw->dwm_maxsize)) { pdwvw->bit_count -= 1 ; if (pdwvw->bits & (1 << pdwvw->bit_count)) break ; output += 1 ; } ; return output ; } /* dwvw_decode_load_bits */ static void dwvw_read_reset (DWVW_PRIVATE *pdwvw) { pdwvw->samplecount = 0 ; pdwvw->b.index = 0 ; pdwvw->b.end = 0 ; pdwvw->bit_count = 0 ; pdwvw->bits = 0 ; pdwvw->last_delta_width = 0 ; pdwvw->last_sample = 0 ; } /* dwvw_read_reset */ static void dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) { int byte ; /* Shift the bits into the resevoir. */ pdwvw->bits = (pdwvw->bits << new_bits) | (data & ((1 << new_bits) - 1)) ; pdwvw->bit_count += new_bits ; /* Transfer bit to buffer. */ while (pdwvw->bit_count >= 8) { byte = pdwvw->bits >> (pdwvw->bit_count - 8) ; pdwvw->bit_count -= 8 ; pdwvw->b.buffer [pdwvw->b.index] = byte & 0xFF ; pdwvw->b.index ++ ; } ; if (pdwvw->b.index > SIGNED_SIZEOF (pdwvw->b.buffer) - 4) { psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ; pdwvw->b.index = 0 ; } ; return ; } /* dwvw_encode_store_bits */ #if 0 /* Debigging routine. */ static void dump_bits (DWVW_PRIVATE *pdwvw) { int k, mask ; for (k = 0 ; k < 10 && k < pdwvw->b.index ; k++) { mask = 0x80 ; while (mask) { putchar (mask & pdwvw->b.buffer [k] ? '1' : '0') ; mask >>= 1 ; } ; putchar (' ') ; } for (k = pdwvw->bit_count - 1 ; k >= 0 ; k --) putchar (pdwvw->bits & (1 << k) ? '1' : '0') ; putchar ('\n') ; } /* dump_bits */ #endif #define HIGHEST_BIT(x,count) \ { int y = x ; \ (count) = 0 ; \ while (y) \ { (count) ++ ; \ y >>= 1 ; \ } ; \ } ; static int dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) { int count ; int delta_width_modifier, delta, delta_negative, delta_width, extra_bit ; for (count = 0 ; count < len ; count++) { delta = (ptr [count] >> (32 - pdwvw->bit_width)) - pdwvw->last_sample ; /* Calculate extra_bit if needed. */ extra_bit = -1 ; delta_negative = 0 ; if (delta < -pdwvw->max_delta) delta = pdwvw->max_delta + (delta % pdwvw->max_delta) ; else if (delta == -pdwvw->max_delta) { extra_bit = 1 ; delta_negative = 1 ; delta = pdwvw->max_delta - 1 ; } else if (delta > pdwvw->max_delta) { delta_negative = 1 ; delta = pdwvw->span - delta ; delta = abs (delta) ; } else if (delta == pdwvw->max_delta) { extra_bit = 1 ; delta = pdwvw->max_delta - 1 ; } else if (delta < 0) { delta_negative = 1 ; delta = abs (delta) ; } ; if (delta == pdwvw->max_delta - 1 && extra_bit == -1) extra_bit = 0 ; /* Find width in bits of delta */ HIGHEST_BIT (delta, delta_width) ; /* Calculate the delta_width_modifier */ delta_width_modifier = (delta_width - pdwvw->last_delta_width) % pdwvw->bit_width ; if (delta_width_modifier > pdwvw->dwm_maxsize) delta_width_modifier -= pdwvw->bit_width ; if (delta_width_modifier < -pdwvw->dwm_maxsize) delta_width_modifier += pdwvw->bit_width ; /* Write delta_width_modifier zeros, followed by terminating '1'. */ dwvw_encode_store_bits (psf, pdwvw, 0, abs (delta_width_modifier)) ; if (abs (delta_width_modifier) != pdwvw->dwm_maxsize) dwvw_encode_store_bits (psf, pdwvw, 1, 1) ; /* Write delta_width_modifier sign. */ if (delta_width_modifier < 0) dwvw_encode_store_bits (psf, pdwvw, 1, 1) ; if (delta_width_modifier > 0) dwvw_encode_store_bits (psf, pdwvw, 0, 1) ; /* Write delta and delta sign bit. */ if (delta_width) { dwvw_encode_store_bits (psf, pdwvw, delta, abs (delta_width) - 1) ; dwvw_encode_store_bits (psf, pdwvw, (delta_negative ? 1 : 0), 1) ; } ; /* Write extra bit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ if (extra_bit >= 0) dwvw_encode_store_bits (psf, pdwvw, extra_bit, 1) ; pdwvw->last_sample = ptr [count] >> (32 - pdwvw->bit_width) ; pdwvw->last_delta_width = delta_width ; } ; pdwvw->samplecount += count ; return count ; } /* dwvw_encode_data */ static sf_count_t dwvw_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = ptr [total + k] << 16 ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* dwvw_write_s */ static sf_count_t dwvw_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = dwvw_encode_data (psf, pdwvw, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* dwvw_write_i */ static sf_count_t dwvw_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = lrintf (normfact * ptr [total + k]) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* dwvw_write_f */ static sf_count_t dwvw_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { DWVW_PRIVATE *pdwvw ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pdwvw = (DWVW_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ; iptr = (int*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = lrint (normfact * ptr [total + k]) ; count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* dwvw_write_d */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 1ca09552-b01f-4d7f-9bcf-612f834fe41d */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** Copyright (C) 2003 Ross Bencina ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** This header file MUST be included before the others to ensure that ** large file support is enabled. */ #include #include #ifdef HAVE_UNISTD_H #include #endif #if (HAVE_DECL_S_IRGRP == 0) #include #endif #include #include #include #include #if (defined (__MWERKS__) && defined (macintosh)) typedef int ssize_t ; #include #endif #define SENSIBLE_SIZE (0x40000000) static void psf_log_syserr (SF_PRIVATE *psf, int error) ; #if ((defined (WIN32) || defined (_WIN32)) == 0) /*------------------------------------------------------------------------------ ** Win32 stuff at the bottom of the file. Unix and other sensible OSes here. */ int psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) { int oflag, mode ; /* ** Sanity check. If everything is OK, this test and the printfs will ** be optimised out. This is meant to catch the problems caused by ** "config.h" being included after . */ if (sizeof (off_t) != sizeof (sf_count_t)) { puts ("\n\n*** Fatal error : sizeof (off_t) != sizeof (sf_count_t)") ; puts ("*** This means that libsndfile was not configured correctly.\n") ; exit (1) ; } ; switch (open_mode) { case SFM_READ : oflag = O_RDONLY ; mode = 0 ; break ; case SFM_WRITE : oflag = O_WRONLY | O_CREAT | O_TRUNC ; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ; break ; case SFM_RDWR : oflag = O_RDWR | O_CREAT ; mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ; break ; default : psf->error = SFE_BAD_OPEN_MODE ; return psf->error ; break ; } ; #if defined (__CYGWIN__) oflag |= O_BINARY ; #endif if (mode == 0) psf->filedes = open (pathname, oflag) ; else psf->filedes = open (pathname, oflag, mode) ; if (psf->filedes == -1) psf_log_syserr (psf, errno) ; psf->mode = open_mode ; return psf->error ; } /* psf_fopen */ int psf_set_stdio (SF_PRIVATE *psf, int mode) { int error = 0 ; switch (mode) { case SFM_RDWR : error = SFE_OPEN_PIPE_RDWR ; break ; case SFM_READ : psf->filedes = 0 ; break ; case SFM_WRITE : psf->filedes = 1 ; break ; default : error = SFE_BAD_OPEN_MODE ; break ; } ; psf->filelength = 0 ; return error ; } /* psf_set_stdio */ void psf_set_file (SF_PRIVATE *psf, int fd) { psf->filedes = fd ; } /* psf_set_file */ int psf_filedes_valid (SF_PRIVATE *psf) { return (psf->filedes >= 0) ? SF_TRUE : SF_FALSE ; } /* psf_set_file */ sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) { sf_count_t new_position ; switch (whence) { case SEEK_SET : offset += psf->fileoffset ; break ; case SEEK_END : if (psf->mode == SFM_WRITE) { new_position = lseek (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; return new_position - psf->fileoffset ; } ; /* Transform SEEK_END into a SEEK_SET, ie find the file ** length add the requested offset (should be <= 0) to ** get the offset wrt the start of file. */ whence = SEEK_SET ; offset = lseek (psf->filedes, 0, SEEK_END) + offset ; break ; default : /* No need to do anything about SEEK_CUR. */ break ; } ; new_position = lseek (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; new_position -= psf->fileoffset ; return new_position ; } /* psf_fseek */ sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ; } /* psf_fread */ sf_count_t psf_fwrite (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; count = write (psf->filedes, ((char*) ptr) + total, count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ; } /* psf_fwrite */ sf_count_t psf_ftell (SF_PRIVATE *psf) { sf_count_t pos ; if (psf->is_pipe) return psf->pipeoffset ; pos = lseek (psf->filedes, 0, SEEK_CUR) ; if (pos == ((sf_count_t) -1)) { psf_log_syserr (psf, errno) ; return -1 ; } ; return pos - psf->fileoffset ; } /* psf_ftell */ int psf_fclose (SF_PRIVATE *psf) { int retval ; #if ((defined (__MWERKS__) && defined (macintosh)) == 0) /* Must be MacOS9 which doesn't have fsync(). */ if (fsync (psf->filedes) == -1 && errno == EBADF) return 0 ; #endif if (psf->do_not_close_descriptor) { psf->filedes = -1 ; return 0 ; } ; while ((retval = close (psf->filedes)) == -1 && errno == EINTR) /* Do nothing. */ ; if (retval == -1) psf_log_syserr (psf, errno) ; psf->filedes = -1 ; return retval ; } /* psf_fclose */ sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) { sf_count_t k = 0 ; sf_count_t count ; while (k < bufsize - 1) { count = read (psf->filedes, &(buffer [k]), 1) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0 || buffer [k++] == '\n') break ; } ; buffer [k] = 0 ; return k ; } /* psf_fgets */ int psf_is_pipe (SF_PRIVATE *psf) { struct stat statbuf ; if (fstat (psf->filedes, &statbuf) == -1) { psf_log_syserr (psf, errno) ; /* Default to maximum safety. */ return SF_TRUE ; } ; if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) return SF_TRUE ; return SF_FALSE ; } /* psf_is_pipe */ sf_count_t psf_get_filelen (SF_PRIVATE *psf) { struct stat statbuf ; sf_count_t filelen ; /* ** Sanity check. ** If everything is OK, this will be optimised out. */ if (sizeof (statbuf.st_size) == 4 && sizeof (sf_count_t) == 8) return SFE_BAD_STAT_SIZE ; /* Cygwin seems to need this. */ #if (defined (__CYGWIN__) && HAVE_FSYNC) fsync (psf->filedes) ; #endif if (fstat (psf->filedes, &statbuf) == -1) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; switch (psf->mode) { case SFM_WRITE : filelen = statbuf.st_size - psf->fileoffset ; break ; case SFM_READ : if (psf->fileoffset > 0 && psf->filelength > 0) filelen = psf->filelength ; else filelen = statbuf.st_size ; break ; case SFM_RDWR : /* ** Cannot open embedded files SFM_RDWR so we don't need to ** subtract psf->fileoffset. We already have the answer we ** need. */ filelen = statbuf.st_size ; break ; default : /* Shouldn't be here, so return error. */ filelen = -1 ; } ; return filelen ; } /* psf_get_filelen */ int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) { int retval ; /* Returns 0 on success, non-zero on failure. */ if (len < 0) return -1 ; if ((sizeof (off_t) < sizeof (sf_count_t)) && len > 0x7FFFFFFF) return -1 ; #if (defined (__MWERKS__) && defined (macintosh)) retval = FSSetForkSize (psf->filedes, fsFromStart, len) ; #else retval = ftruncate (psf->filedes, len) ; #endif if (retval == -1) psf_log_syserr (psf, errno) ; return retval ; } /* psf_ftruncate */ static void psf_log_syserr (SF_PRIVATE *psf, int error) { /* Only log an error if no error has been set yet. */ if (psf->error == 0) { psf->error = SFE_SYSTEM ; LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s.", strerror (error)) ; } ; return ; } /* psf_log_syserr */ //XXX formerly OS_IS_WIN32 #elif __PLATFORM_WIN32__ /* Win32 file i/o functions implemented using native Win32 API */ #include #include #ifndef HAVE_SSIZE_T typedef long ssize_t ; #endif /* Win32 */ static void psf_log_syserr (SF_PRIVATE *psf, int error) { LPVOID lpMsgBuf ; /* Only log an error if no error has been set yet. */ if (psf->error == 0) { psf->error = SFE_SYSTEM ; FormatMessage ( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ) ; LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s", lpMsgBuf) ; LocalFree (lpMsgBuf) ; } ; return ; } /* psf_log_syserr */ /* Win32 */ int psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) { DWORD dwDesiredAccess ; DWORD dwShareMode ; DWORD dwCreationDistribution ; HANDLE handle ; switch (open_mode) { case SFM_READ : dwDesiredAccess = GENERIC_READ ; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; dwCreationDistribution = OPEN_EXISTING ; break ; case SFM_WRITE : dwDesiredAccess = GENERIC_WRITE ; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; dwCreationDistribution = CREATE_ALWAYS ; break ; case SFM_RDWR : dwDesiredAccess = GENERIC_READ | GENERIC_WRITE ; dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE ; dwCreationDistribution = OPEN_ALWAYS ; break ; default : psf->error = SFE_BAD_OPEN_MODE ; return psf->error ; } ; handle = CreateFile ( pathname, /* pointer to name of the file */ dwDesiredAccess, /* access (read-write) mode */ dwShareMode, /* share mode */ 0, /* pointer to security attributes */ dwCreationDistribution, /* how to create */ FILE_ATTRIBUTE_NORMAL, /* file attributes (could use FILE_FLAG_SEQUENTIAL_SCAN) */ NULL /* handle to file with attributes to copy */ ) ; if (handle == INVALID_HANDLE_VALUE) { psf_log_syserr (psf, GetLastError ()) ; return psf->error ; } ; psf->filedes = (int) handle ; psf->mode = open_mode ; return psf->error ; } /* psf_fopen */ /* Win32 */ int psf_set_stdio (SF_PRIVATE *psf, int mode) { HANDLE handle = NULL ; int error = 0 ; switch (mode) { case SFM_RDWR : error = SFE_OPEN_PIPE_RDWR ; break ; case SFM_READ : handle = GetStdHandle (STD_INPUT_HANDLE) ; psf->do_not_close_descriptor = 1 ; break ; case SFM_WRITE : handle = GetStdHandle (STD_OUTPUT_HANDLE) ; psf->do_not_close_descriptor = 1 ; break ; default : error = SFE_BAD_OPEN_MODE ; break ; } ; psf->filedes = (int) handle ; psf->filelength = 0 ; return error ; } /* psf_set_stdio */ /* Win32 */ void psf_set_file (SF_PRIVATE *psf, int fd) { HANDLE handle ; long osfhandle ; osfhandle = _get_osfhandle (fd) ; handle = (HANDLE) osfhandle ; if (GetFileType (handle) == FILE_TYPE_DISK) psf->filedes = (int) handle ; else psf->filedes = fd ; } /* psf_set_file */ /* Win32 */ int psf_filedes_valid (SF_PRIVATE *psf) { return (((HANDLE) psf->filedes) != INVALID_HANDLE_VALUE) ? SF_TRUE : SF_FALSE ; } /* psf_set_file */ /* Win32 */ sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) { sf_count_t new_position ; LONG lDistanceToMove, lDistanceToMoveHigh ; DWORD dwMoveMethod ; DWORD dwResult, dwError ; switch (whence) { case SEEK_SET : offset += psf->fileoffset ; dwMoveMethod = FILE_BEGIN ; break ; case SEEK_END : dwMoveMethod = FILE_END ; break ; default : dwMoveMethod = FILE_CURRENT ; break ; } ; lDistanceToMove = (DWORD) (offset & 0xFFFFFFFF) ; #ifndef __WINDOWS_DS__ lDistanceToMoveHigh = (DWORD) (0xFFFFFFFF & (offset >> 32)) ; #else lDistanceToMoveHigh = 0; #endif dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMove, &lDistanceToMoveHigh, dwMoveMethod) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; else dwError = NO_ERROR ; if (dwError != NO_ERROR) { psf_log_syserr (psf, dwError) ; return -1 ; } ; new_position = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) - psf->fileoffset ; return new_position ; } /* psf_fseek */ /* Win32 */ sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; DWORD dwNumberOfBytesRead ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; if( items == 16384 ) count = 1024; if (ReadFile ((HANDLE) psf->filedes, ((char*) ptr) + total, count, &dwNumberOfBytesRead, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else count = dwNumberOfBytesRead ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ; } /* psf_fread */ /* Win32 */ sf_count_t psf_fwrite (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; DWORD dwNumberOfBytesWritten ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; if (WriteFile ((HANDLE) psf->filedes, ((char*) ptr) + total, count, &dwNumberOfBytesWritten, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else count = dwNumberOfBytesWritten ; if (count == 0) break ; total += count ; items -= count ; } ; if (psf->is_pipe) psf->pipeoffset += total ; return total / bytes ; } /* psf_fwrite */ /* Win32 */ sf_count_t psf_ftell (SF_PRIVATE *psf) { sf_count_t pos ; LONG lDistanceToMoveLow, lDistanceToMoveHigh ; DWORD dwResult, dwError ; if (psf->is_pipe) return psf->pipeoffset ; lDistanceToMoveLow = 0 ; lDistanceToMoveHigh = 0 ; dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMoveLow, NULL, FILE_CURRENT) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; else dwError = NO_ERROR ; if (dwError != NO_ERROR) { psf_log_syserr (psf, dwError) ; return -1 ; } ; pos = (dwResult + ((__int64) lDistanceToMoveHigh << 32)) ; return pos - psf->fileoffset ; } /* psf_ftell */ /* Win32 */ int psf_fclose (SF_PRIVATE *psf) { int retval = 0 ; if (psf->do_not_close_descriptor) { (HANDLE) psf->filedes = INVALID_HANDLE_VALUE ; return 0 ; } ; if (CloseHandle ((HANDLE) psf->filedes) == 0) { retval = -1 ; psf_log_syserr (psf, GetLastError ()) ; } ; psf->filedes = (int) INVALID_HANDLE_VALUE ; return retval ; } /* psf_fclose */ /* Win32 */ sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) { sf_count_t k = 0 ; sf_count_t count ; DWORD dwNumberOfBytesRead ; while (k < bufsize - 1) { if (ReadFile ((HANDLE) psf->filedes, &(buffer [k]), 1, &dwNumberOfBytesRead, 0) == 0) { psf_log_syserr (psf, GetLastError ()) ; break ; } else { count = dwNumberOfBytesRead ; /* note that we only check for '\n' not other line endings such as CRLF */ if (count == 0 || buffer [k++] == '\n') break ; } ; } ; buffer [k] = '\0' ; return k ; } /* psf_fgets */ /* Win32 */ int psf_is_pipe (SF_PRIVATE *psf) { if (GetFileType ((HANDLE) psf->filedes) == FILE_TYPE_DISK) return SF_FALSE ; /* Default to maximum safety. */ return SF_TRUE ; } /* psf_is_pipe */ /* Win32 */ sf_count_t psf_get_filelen (SF_PRIVATE *psf) { sf_count_t filelen ; DWORD dwFileSizeLow, dwFileSizeHigh, dwError = NO_ERROR ; dwFileSizeLow = GetFileSize ((HANDLE) psf->filedes, &dwFileSizeHigh) ; if (dwFileSizeLow == 0xFFFFFFFF) dwError = GetLastError () ; if (dwError != NO_ERROR) { psf_log_syserr (psf, GetLastError ()) ; return 0 ; } else filelen = dwFileSizeLow + ((__int64) dwFileSizeHigh << 32) ; switch (psf->mode) { case SFM_WRITE : filelen = filelen - psf->fileoffset ; break ; case SFM_READ : if (psf->fileoffset > 0 && psf->filelength > 0) filelen = psf->filelength ; break ; case SFM_RDWR : /* ** Cannot open embedded files SFM_RDWR so we don't need to ** subtract psf->fileoffset. We already have the answer we ** need. */ break ; default : /* Shouldn't be here, so return error. */ filelen = -1 ; } ; return filelen ; } /* psf_get_filelen */ /* Win32 */ int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) { int retval = 0 ; LONG lDistanceToMoveLow, lDistanceToMoveHigh ; DWORD dwResult, dwError = NO_ERROR ; /* This implementation trashes the current file position. ** should it save and restore it? what if the current position is past ** the new end of file? */ /* Returns 0 on success, non-zero on failure. */ if (len < 0) return 1 ; lDistanceToMoveLow = (DWORD) (len & 0xFFFFFFFF) ; #ifndef __WINDOWS_DS__ lDistanceToMoveHigh = (DWORD) ((len >> 32) & 0xFFFFFFFF) ; #else lDistanceToMoveHigh = 0; #endif dwResult = SetFilePointer ((HANDLE) psf->filedes, lDistanceToMoveLow, &lDistanceToMoveHigh, FILE_BEGIN) ; if (dwResult == 0xFFFFFFFF) dwError = GetLastError () ; if (dwError != NO_ERROR) { retval = -1 ; psf_log_syserr (psf, dwError) ; } else { /* Note: when SetEndOfFile is used to extend a file, the contents of the ** new portion of the file is undefined. This is unlike chsize(), ** which guarantees that the new portion of the file will be zeroed. ** Not sure if this is important or not. */ if (SetEndOfFile ((HANDLE) psf->filedes) == 0) { retval = -1 ; psf_log_syserr (psf, GetLastError ()) ; } ; } ; return retval ; } /* psf_ftruncate */ #else /* Win32 file i/o functions implemented using Unix-style file i/o API */ /* Win32 has a 64 file offset seek function: ** ** __int64 _lseeki64 (int handle, __int64 offset, int origin) ; ** ** It also has a 64 bit fstat function: ** ** int fstati64 (int, struct _stati64) ; ** ** but the fscking thing doesn't work!!!!! The file size parameter returned ** by this function is only valid up until more data is written at the end of ** the file. That makes this function completely 100% useless. */ #include #include #ifndef HAVE_SSIZE_T typedef long ssize_t ; #endif /* Win32 */ int psf_fopen (SF_PRIVATE *psf, const char *pathname, int open_mode) { int oflag, mode ; switch (open_mode) { case SFM_READ : oflag = O_RDONLY | O_BINARY ; mode = 0 ; break ; case SFM_WRITE : oflag = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ; mode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; case SFM_RDWR : oflag = O_RDWR | O_CREAT | O_BINARY ; mode = S_IRUSR | S_IWUSR | S_IRGRP ; break ; default : psf->error = SFE_BAD_OPEN_MODE ; return -1 ; break ; } ; if (mode == 0) psf->filedes = open (pathname, oflag) ; else psf->filedes = open (pathname, oflag, mode) ; if (psf->filedes == -1) psf_log_syserr (psf, errno) ; return psf->filedes ; } /* psf_fopen */ /* Win32 */ sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) { sf_count_t new_position ; switch (whence) { case SEEK_SET : offset += psf->fileoffset ; break ; case SEEK_END : if (psf->mode == SFM_WRITE) { new_position = _lseeki64 (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; return new_position - psf->fileoffset ; } ; /* Transform SEEK_END into a SEEK_SET, ie find the file ** length add the requested offset (should be <= 0) to ** get the offset wrt the start of file. */ whence = SEEK_SET ; offset = _lseeki64 (psf->filedes, 0, SEEK_END) + offset ; break ; default : /* No need to do anything about SEEK_CUR. */ break ; } ; /* ** Bypass weird Win32-ism if necessary. ** _lseeki64() returns an "invalid parameter" error if called with the ** offset == 0 and whence == SEEK_CUR. *** Use the _telli64() function instead. */ if (offset == 0 && whence == SEEK_CUR) new_position = _telli64 (psf->filedes) ; else new_position = _lseeki64 (psf->filedes, offset, whence) ; if (new_position < 0) psf_log_syserr (psf, errno) ; new_position -= psf->fileoffset ; return new_position ; } /* psf_fseek */ /* Win32 */ sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : (ssize_t) items ; count = read (psf->filedes, ((char*) ptr) + total, (size_t) count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; return total / bytes ; } /* psf_fread */ /* Win32 */ sf_count_t psf_fwrite (void *ptr, sf_count_t bytes, sf_count_t items, SF_PRIVATE *psf) { sf_count_t total = 0 ; ssize_t count ; items *= bytes ; /* Do this check after the multiplication above. */ if (items <= 0) return 0 ; while (items > 0) { /* Break the writes down to a sensible size. */ count = (items > SENSIBLE_SIZE) ? SENSIBLE_SIZE : items ; count = write (psf->filedes, ((char*) ptr) + total, count) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0) break ; total += count ; items -= count ; } ; return total / bytes ; } /* psf_fwrite */ /* Win32 */ sf_count_t psf_ftell (SF_PRIVATE *psf) { sf_count_t pos ; pos = _telli64 (psf->filedes) ; if (pos == ((sf_count_t) -1)) { psf_log_syserr (psf, errno) ; return -1 ; } ; return pos - psf->fileoffset ; } /* psf_ftell */ /* Win32 */ int psf_fclose (SF_PRIVATE *psf) { int retval ; while ((retval = close (psf->filedes)) == -1 && errno == EINTR) /* Do nothing. */ ; if (retval == -1) psf_log_syserr (psf, errno) ; psf->filedes = -1 ; return retval ; } /* psf_fclose */ /* Win32 */ sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) { sf_count_t k = 0 ; sf_count_t count ; while (k < bufsize - 1) { count = read (psf->filedes, &(buffer [k]), 1) ; if (count == -1) { if (errno == EINTR) continue ; psf_log_syserr (psf, errno) ; break ; } ; if (count == 0 || buffer [k++] == '\n') break ; } ; buffer [k] = 0 ; return k ; } /* psf_fgets */ /* Win32 */ int psf_is_pipe (SF_PRIVATE *psf) { struct stat statbuf ; /* Not sure if this works. */ if (fstat (psf->filedes, &statbuf) == -1) { psf_log_syserr (psf, errno) ; /* Default to maximum safety. */ return SF_TRUE ; } ; /* These macros are defined in Win32/unistd.h. */ if (S_ISFIFO (statbuf.st_mode) || S_ISSOCK (statbuf.st_mode)) return SF_TRUE ; return SF_FALSE ; } /* psf_checkpipe */ /* Win32 */ sf_count_t psf_get_filelen (SF_PRIVATE *psf) { #if 0 /* ** Windoze is SOOOOO FUCKED!!!!!!! ** This code should work but doesn't. Why? ** Code below does work. */ struct _stati64 statbuf ; if (_fstati64 (psf->filedes, &statbuf)) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; return statbuf.st_size ; #else sf_count_t current, filelen ; if ((current = _telli64 (psf->filedes)) < 0) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; /* ** Lets face it, windoze if FUBAR!!! ** ** For some reason, I have to call _lseeki64() TWICE to get to the ** end of the file. ** ** This might have been avoided if windows had implemented the POSIX ** standard function fsync() but NO, that would have been too easy. ** ** I am VERY close to saying that windoze will no longer be supported ** by libsndfile and changing the license to GPL at the same time. */ _lseeki64 (psf->filedes, 0, SEEK_END) ; if ((filelen = _lseeki64 (psf->filedes, 0, SEEK_END)) < 0) { psf_log_syserr (psf, errno) ; return (sf_count_t) -1 ; } ; if (filelen > current) _lseeki64 (psf->filedes, current, SEEK_SET) ; switch (psf->mode) { case SFM_WRITE : filelen = filelen - psf->fileoffset ; break ; case SFM_READ : if (psf->fileoffset > 0 && psf->filelength > 0) filelen = psf->filelength ; break ; case SFM_RDWR : /* ** Cannot open embedded files SFM_RDWR so we don't need to ** subtract psf->fileoffset. We already have the answer we ** need. */ break ; default : filelen = 0 ; } ; return filelen ; #endif } /* psf_get_filelen */ /* Win32 */ int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) { int retval ; /* Returns 0 on success, non-zero on failure. */ if (len < 0) return 1 ; /* The global village idiots at micorsoft decided to implement ** nearly all the required 64 bit file offset functions except ** for one, truncate. The fscking morons! ** ** This is not 64 bit file offset clean. Somone needs to clean ** this up. */ if (len > 0x7FFFFFFF) return -1 ; retval = chsize (psf->filedes, len) ; if (retval == -1) psf_log_syserr (psf, errno) ; return retval ; } /* psf_ftruncate */ static void psf_log_syserr (SF_PRIVATE *psf, int error) { /* Only log an error if no error has been set yet. */ if (psf->error == 0) { psf->error = SFE_SYSTEM ; LSF_SNPRINTF (psf->syserr, sizeof (psf->syserr), "System error : %s", strerror (error)) ; } ; return ; } /* psf_log_syserr */ #endif /*============================================================================== */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 749740d7-ecc7-47bd-8cf7-600f31d32e6d */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #if CPU_IS_LITTLE_ENDIAN #define FLOAT32_READ float32_le_read #define FLOAT32_WRITE float32_le_write #elif CPU_IS_BIG_ENDIAN #define FLOAT32_READ float32_be_read #define FLOAT32_WRITE float32_be_write #endif /*-------------------------------------------------------------------------------------------- ** Processor floating point capabilities. float32_get_capability () returns one of the ** latter four values. */ enum { FLOAT_UNKNOWN = 0x00, FLOAT_CAN_RW_LE = 0x12, FLOAT_CAN_RW_BE = 0x23, FLOAT_BROKEN_LE = 0x34, FLOAT_BROKEN_BE = 0x45 } ; /*-------------------------------------------------------------------------------------------- ** Prototypes for private functions. */ static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t host_write_s2f (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t host_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t host_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t host_write_d2f (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void f2s_array (float *src, int count, short *dest) ; static void f2i_array (float *src, int count, int *dest) ; static void float32f2d_array (float *src, int count, double *dest) ; static void s2f_array (short *src, float *dest, int count) ; static void i2f_array (int *src, float *dest, int count) ; static void float32d2f_array (double *src, float *dest, int count) ; static void float32_peak_update (SF_PRIVATE *psf, float *buffer, int count, int indx) ; static sf_count_t replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t replace_write_s2f (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t replace_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t replace_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t replace_write_d2f (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void bf2f_array (float *buffer, int count) ; static void f2bf_array (float *buffer, int count) ; static int float32_get_capability (SF_PRIVATE *psf) ; /*-------------------------------------------------------------------------------------------- ** Exported functions. */ int float32_init (SF_PRIVATE *psf) { static int float_caps ; float_caps = float32_get_capability (psf) ; psf->blockwidth = sizeof (float) * psf->sf.channels ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { switch (psf->endian + float_caps) { case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) : psf->float_endswap = SF_FALSE ; psf->read_short = host_read_f2s ; psf->read_int = host_read_f2i ; psf->read_float = host_read_f ; psf->read_double = host_read_f2d ; break ; case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) : psf->float_endswap = SF_FALSE ; psf->read_short = host_read_f2s ; psf->read_int = host_read_f2i ; psf->read_float = host_read_f ; psf->read_double = host_read_f2d ; break ; case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) : psf->float_endswap = SF_TRUE ; psf->read_short = host_read_f2s ; psf->read_int = host_read_f2i ; psf->read_float = host_read_f ; psf->read_double = host_read_f2d ; break ; case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) : psf->float_endswap = SF_TRUE ; psf->read_short = host_read_f2s ; psf->read_int = host_read_f2i ; psf->read_float = host_read_f ; psf->read_double = host_read_f2d ; break ; /* When the CPU is not IEEE compatible. */ case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) : psf->float_endswap = SF_TRUE ; psf->read_short = replace_read_f2s ; psf->read_int = replace_read_f2i ; psf->read_float = replace_read_f ; psf->read_double = replace_read_f2d ; break ; case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) : psf->float_endswap = SF_FALSE ; psf->read_short = replace_read_f2s ; psf->read_int = replace_read_f2i ; psf->read_float = replace_read_f ; psf->read_double = replace_read_f2d ; break ; case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) : psf->float_endswap = SF_FALSE ; psf->read_short = replace_read_f2s ; psf->read_int = replace_read_f2i ; psf->read_float = replace_read_f ; psf->read_double = replace_read_f2d ; break ; case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) : psf->float_endswap = SF_TRUE ; psf->read_short = replace_read_f2s ; psf->read_int = replace_read_f2i ; psf->read_float = replace_read_f ; psf->read_double = replace_read_f2d ; break ; default : break ; } ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { switch (psf->endian + float_caps) { case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) : psf->float_endswap = SF_FALSE ; psf->write_short = host_write_s2f ; psf->write_int = host_write_i2f ; psf->write_float = host_write_f ; psf->write_double = host_write_d2f ; break ; case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) : psf->float_endswap = SF_FALSE ; psf->write_short = host_write_s2f ; psf->write_int = host_write_i2f ; psf->write_float = host_write_f ; psf->write_double = host_write_d2f ; break ; case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) : psf->float_endswap = SF_TRUE ; psf->write_short = host_write_s2f ; psf->write_int = host_write_i2f ; psf->write_float = host_write_f ; psf->write_double = host_write_d2f ; break ; case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) : psf->float_endswap = SF_TRUE ; psf->write_short = host_write_s2f ; psf->write_int = host_write_i2f ; psf->write_float = host_write_f ; psf->write_double = host_write_d2f ; break ; /* When the CPU is not IEEE compatible. */ case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) : psf->float_endswap = SF_TRUE ; psf->write_short = replace_write_s2f ; psf->write_int = replace_write_i2f ; psf->write_float = replace_write_f ; psf->write_double = replace_write_d2f ; break ; case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) : psf->float_endswap = SF_FALSE ; psf->write_short = replace_write_s2f ; psf->write_int = replace_write_i2f ; psf->write_float = replace_write_f ; psf->write_double = replace_write_d2f ; break ; case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) : psf->float_endswap = SF_FALSE ; psf->write_short = replace_write_s2f ; psf->write_int = replace_write_i2f ; psf->write_float = replace_write_f ; psf->write_double = replace_write_d2f ; break ; case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) : psf->float_endswap = SF_TRUE ; psf->write_short = replace_write_s2f ; psf->write_int = replace_write_i2f ; psf->write_float = replace_write_f ; psf->write_double = replace_write_d2f ; break ; default : break ; } ; } ; if (psf->filelength > psf->dataoffset) { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; } else psf->datalength = 0 ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* float32_init */ float float32_be_read (unsigned char *cptr) { int exponent, mantissa, negative ; float fvalue ; negative = cptr [0] & 0x80 ; exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ; mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ; if (! (exponent || mantissa)) return 0.0 ; mantissa |= 0x800000 ; exponent = exponent ? exponent - 127 : 0 ; fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; if (negative) fvalue *= -1 ; if (exponent > 0) fvalue *= (1 << exponent) ; else if (exponent < 0) fvalue /= (1 << abs (exponent)) ; return fvalue ; } /* float32_be_read */ float float32_le_read (unsigned char *cptr) { int exponent, mantissa, negative ; float fvalue ; negative = cptr [3] & 0x80 ; exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ; mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ; if (! (exponent || mantissa)) return 0.0 ; mantissa |= 0x800000 ; exponent = exponent ? exponent - 127 : 0 ; fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ; if (negative) fvalue *= -1 ; if (exponent > 0) fvalue *= (1 << exponent) ; else if (exponent < 0) fvalue /= (1 << abs (exponent)) ; return fvalue ; } /* float32_le_read */ void float32_le_write (float in, unsigned char *out) { int exponent, mantissa, negative = 0 ; memset (out, 0, sizeof (int)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; negative = 1 ; } ; in = frexp (in, &exponent) ; exponent += 126 ; in *= (float) 0x1000000 ; mantissa = (((int) in) & 0x7FFFFF) ; if (negative) out [3] |= 0x80 ; if (exponent & 0x01) out [2] |= 0x80 ; out [0] = mantissa & 0xFF ; out [1] = (mantissa >> 8) & 0xFF ; out [2] |= (mantissa >> 16) & 0x7F ; out [3] |= (exponent >> 1) & 0x7F ; return ; } /* float32_le_write */ void float32_be_write (float in, unsigned char *out) { int exponent, mantissa, negative = 0 ; memset (out, 0, sizeof (int)) ; if (in == 0.0) return ; if (in < 0.0) { in *= -1.0 ; negative = 1 ; } ; in = frexp (in, &exponent) ; exponent += 126 ; in *= (float) 0x1000000 ; mantissa = (((int) in) & 0x7FFFFF) ; if (negative) out [0] |= 0x80 ; if (exponent & 0x01) out [1] |= 0x80 ; out [3] = mantissa & 0xFF ; out [2] = (mantissa >> 8) & 0xFF ; out [1] |= (mantissa >> 16) & 0x7F ; out [0] |= (exponent >> 1) & 0x7F ; return ; } /* float32_be_write */ /*============================================================================================== ** Private functions. */ static void float32_peak_update (SF_PRIVATE *psf, float *buffer, int count, int indx) { int chan ; int k, position ; float fmaxval ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { fmaxval = fabs (buffer [chan]) ; position = 0 ; for (k = chan ; k < count ; k += psf->sf.channels) if (fmaxval < fabs (buffer [k])) { fmaxval = fabs (buffer [k]) ; position = k ; } ; if (fmaxval > psf->pchunk->peaks [chan].value) { psf->pchunk->peaks [chan].value = fmaxval ; psf->pchunk->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ; } ; } ; return ; } /* float32_peak_update */ static int float32_get_capability (SF_PRIVATE *psf) { union { float f ; int i ; unsigned char c [4] ; } data ; data.f = (float) 1.23456789 ; /* Some abitrary value. */ if (! psf->ieee_replace) { /* If this test is true ints and floats are compatible and little endian. */ if (data.c [0] == 0x52 && data.c [1] == 0x06 && data.c [2] == 0x9e && data.c [3] == 0x3f) return FLOAT_CAN_RW_LE ; /* If this test is true ints and floats are compatible and big endian. */ if (data.c [3] == 0x52 && data.c [2] == 0x06 && data.c [1] == 0x9e && data.c [0] == 0x3f) return FLOAT_CAN_RW_BE ; } ; /* Floats are broken. Don't expect reading or writing to be fast. */ psf_log_printf (psf, "Using IEEE replacement code for float.\n") ; return (CPU_IS_LITTLE_ENDIAN) ? FLOAT_BROKEN_LE : FLOAT_BROKEN_BE ; } /* float32_get_capability */ /*---------------------------------------------------------------------------------------------- */ static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; /* Fix me : Need lef2s_array */ if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; f2s_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* host_read_f2s */ static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; f2i_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* host_read_f2i */ static sf_count_t host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if (psf->float_endswap != SF_TRUE) return psf_fread (ptr, sizeof (float), len, psf) ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; endswap_int_copy ((int*) (ptr + total), (int*) psf->buffer, thisread) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* host_read_f */ static sf_count_t host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; /* Fix me : Need lefloat32f2d_array */ float32f2d_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* host_read_f2d */ static sf_count_t host_write_s2f (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* host_write_s2f */ static sf_count_t host_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float) , writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* host_write_i2f */ static sf_count_t host_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if (psf->has_peak) float32_peak_update (psf, ptr, len, 0) ; if (psf->float_endswap != SF_TRUE) return psf_fwrite (ptr, sizeof (float), len, psf) ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_int_copy ((int*) psf->buffer, (int*) (ptr + total), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* host_write_f */ static sf_count_t host_write_d2f (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; float32d2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* host_write_d2f */ /*======================================================================================= */ static void f2s_array (float *src, int count, short *dest) { while (count) { count -- ; dest [count] = lrintf (src [count]) ; } ; } /* f2s_array */ static void f2i_array (float *src, int count, int *dest) { while (count) { count -- ; dest [count] = lrintf (src [count]) ; } ; } /* f2i_array */ static void float32f2d_array (float *src, int count, double *dest) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* float32f2d_array */ static void s2f_array (short *src, float *dest, int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* s2f_array */ static void i2f_array (int *src, float *dest, int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* i2f_array */ static void float32d2f_array (double *src, float *dest, int count) { while (count) { count -- ; dest [count] = src [count] ; } ; } /* float32d2f_array */ /*======================================================================================= */ static sf_count_t replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; bf2f_array ((float *) (psf->buffer), readcount) ; f2s_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_f2s */ static sf_count_t replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; bf2f_array ((float *) (psf->buffer), readcount) ; f2i_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_f2i */ static sf_count_t replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; /* FIX THIS */ bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; bf2f_array ((float *) (psf->buffer), readcount) ; memcpy (ptr + total, psf->buffer, readcount * sizeof (float)) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_f */ static sf_count_t replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (float), readcount, psf) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, readcount) ; bf2f_array ((float *) (psf->buffer), readcount) ; float32f2d_array ((float*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* replace_read_f2d */ static sf_count_t replace_write_s2f (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; f2bf_array ((float *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_s2f */ static sf_count_t replace_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; f2bf_array ((float *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_i2f */ static sf_count_t replace_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; /* FIX THIS */ if (psf->has_peak) float32_peak_update (psf, ptr, len, 0) ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; memcpy (psf->buffer, ptr + total, writecount * sizeof (float)) ; f2bf_array ((float *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float) , writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_f */ static sf_count_t replace_write_d2f (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int writecount, bufferlen, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (float) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; float32d2f_array (ptr + total, (float*) (psf->buffer), writecount) ; if (psf->has_peak) float32_peak_update (psf, (float *) (psf->buffer), writecount, (int) (total / psf->sf.channels)) ; f2bf_array ((float *) (psf->buffer), writecount) ; if (psf->float_endswap == SF_TRUE) endswap_int_array ((int*) psf->buffer, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (float), writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* replace_write_d2f */ /*---------------------------------------------------------------------------------------------- */ static void bf2f_array (float *buffer, int count) { while (count) { count -- ; buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ; } ; } /* bf2f_array */ static void f2bf_array (float *buffer, int count) { while (count) { count -- ; FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ; } ; } /* f2bf_array */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: b6c34917-488c-4145-9648-f4371fc4c889 */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * g721.c * * Description: * * g721_encoder(), g721_decoder() * * These routines comprise an implementation of the CCITT G.721 ADPCM * coding algorithm. Essentially, this implementation is identical to * the bit level description except for a few deviations which * take advantage of work station attributes, such as hardware 2's * complement arithmetic and large memory. Specifically, certain time * consuming operations such as multiplications are replaced * with lookup tables and software 2's complement operations are * replaced with hardware 2's complement. * * The deviation from the bit level specification (lookup tables) * preserves the bit level performance specifications. * * As outlined in the G.721 Recommendation, the algorithm is broken * down into modules. Each section of code below is preceded by * the name of the module which it is implementing. * */ static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; /* * Maps G.721 code word to reconstructed scale factor normalized log * magnitude values. */ static short g721_dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, 425, 373, 323, 273, 213, 135, 4, -2048}; /* Maps G.721 code word to log of scale factor multiplier. */ static short g721_witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, 1122, 355, 198, 112, 64, 41, 18, -12}; /* * Maps G.721 code words to a set of values whose long and short * term averages are computed and then compared to give an indication * how stationary (steady state) the signal is. */ static short g721_fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; /* * g721_encoder() * * Encodes the input vale of linear PCM, A-law or u-law data sl and returns * the resulting code. -1 is returned for unknown input coding value. */ int g721_encoder( int sl, G72x_STATE *state_ptr) { short sezi, se, sez; /* ACCUM */ short d; /* SUBTA */ short sr; /* ADDB */ short y; /* MIX */ short dqsez; /* ADDC */ short dq, i; /* linearize input sample to 14-bit PCM */ sl >>= 2; /* 14-bit dynamic range */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ d = sl - se; /* estimation difference */ /* quantize the prediction difference */ y = step_size(state_ptr); /* quantizer step size */ i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ dq = reconstruct(i & 8, g721_dqlntab[i], y); /* quantized est diff */ sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ dqsez = sr + sez - se; /* pole prediction diff. */ update(4, y, g721_witab[i] << 5, g721_fitab[i], dq, sr, dqsez, state_ptr); return (i); } /* * g721_decoder() * * Description: * * Decodes a 4-bit code of G.721 encoded data of i and * returns the resulting linear PCM, A-law or u-law value. * return -1 for unknown out_coding value. */ int g721_decoder( int i, G72x_STATE *state_ptr) { short sezi, sei, sez, se; /* ACCUM */ short y; /* MIX */ short sr; /* ADDB */ short dq; short dqsez; i &= 0x0f; /* mask to get proper bits */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ y = step_size(state_ptr); /* dynamic quantizer step size */ dq = reconstruct(i & 0x08, g721_dqlntab[i], y); /* quantized diff. */ sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ dqsez = sr - se + sez; /* pole prediction diff. */ update(4, y, g721_witab[i] << 5, g721_fitab[i], dq, sr, dqsez, state_ptr); /* sr was 14-bit dynamic range */ return (sr << 2); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 101b6e25-457d-490a-99ae-e2e74a26ea24 */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* 16kbps version created, used 24kbps code and changing as little as possible. * G.726 specs are available from ITU's gopher or WWW site (http://www.itu.ch) * If any errors are found, please contact me at mrand@tamu.edu * -Marc Randolph */ /* * g723_16.c * * Description: * * g723_16_encoder(), g723_16_decoder() * * These routines comprise an implementation of the CCITT G.726 16 Kbps * ADPCM coding algorithm. Essentially, this implementation is identical to * the bit level description except for a few deviations which take advantage * of workstation attributes, such as hardware 2's complement arithmetic. * */ /* * Maps G.723_16 code word to reconstructed scale factor normalized log * magnitude values. Comes from Table 11/G.726 */ static short g723_16_dqlntab[4] = { 116, 365, 365, 116}; /* Maps G.723_16 code word to log of scale factor multiplier. * * g723_16_witab[4] is actually {-22 , 439, 439, -22}, but FILTD wants it * as WI << 5 (multiplied by 32), so we'll do that here */ static short g723_16_witab[4] = {-704, 14048, 14048, -704}; /* * Maps G.723_16 code words to a set of values whose long and short * term averages are computed and then compared to give an indication * how stationary (steady state) the signal is. */ /* Comes from FUNCTF */ static short g723_16_fitab[4] = {0, 0xE00, 0xE00, 0}; /* Comes from quantizer decision level tables (Table 7/G.726) */ static short qtab_723_16[1] = {261}; /* * g723_16_encoder() * * Encodes a linear PCM, A-law or u-law input sample and returns its 2-bit code. * Returns -1 if invalid input coding value. */ int g723_16_encoder( int sl, G72x_STATE *state_ptr) { short sei, sezi, se, sez; /* ACCUM */ short d; /* SUBTA */ short y; /* MIX */ short sr; /* ADDB */ short dqsez; /* ADDC */ short dq, i; /* linearize input sample to 14-bit PCM */ sl >>= 2; /* sl of 14-bit dynamic range */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ d = sl - se; /* d = estimation diff. */ /* quantize prediction difference d */ y = step_size(state_ptr); /* quantizer step size */ i = quantize(d, y, qtab_723_16, 1); /* i = ADPCM code */ /* Since quantize() only produces a three level output * (1, 2, or 3), we must create the fourth one on our own */ if (i == 3) /* i code for the zero region */ if ((d & 0x8000) == 0) /* If d > 0, i=3 isn't right... */ i = 0; dq = reconstruct(i & 2, g723_16_dqlntab[i], y); /* quantized diff. */ sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ dqsez = sr + sez - se; /* pole prediction diff. */ update(2, y, g723_16_witab[i], g723_16_fitab[i], dq, sr, dqsez, state_ptr); return (i); } /* * g723_16_decoder() * * Decodes a 2-bit CCITT G.723_16 ADPCM code and returns * the resulting 16-bit linear PCM, A-law or u-law sample value. * -1 is returned if the output coding is unknown. */ int g723_16_decoder( int i, G72x_STATE *state_ptr) { short sezi, sei, sez, se; /* ACCUM */ short y; /* MIX */ short sr; /* ADDB */ short dq; short dqsez; i &= 0x03; /* mask to get proper bits */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ y = step_size(state_ptr); /* adaptive quantizer step size */ dq = reconstruct(i & 0x02, g723_16_dqlntab[i], y); /* unquantize pred diff */ sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ dqsez = sr - se + sez; /* pole prediction diff. */ update(2, y, g723_16_witab[i], g723_16_fitab[i], dq, sr, dqsez, state_ptr); /* sr was of 14-bit dynamic range */ return (sr << 2); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: ae265466-c3fc-4f83-bb32-edae488a5ca5 */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * g723_24.c * * Description: * * g723_24_encoder(), g723_24_decoder() * * These routines comprise an implementation of the CCITT G.723 24 Kbps * ADPCM coding algorithm. Essentially, this implementation is identical to * the bit level description except for a few deviations which take advantage * of workstation attributes, such as hardware 2's complement arithmetic. * */ /* * Maps G.723_24 code word to reconstructed scale factor normalized log * magnitude values. */ static short g723_24_dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; /* Maps G.723_24 code word to log of scale factor multiplier. */ static short g723_24_witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; /* * Maps G.723_24 code words to a set of values whose long and short * term averages are computed and then compared to give an indication * how stationary (steady state) the signal is. */ static short g723_24_fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; static short qtab_723_24[3] = {8, 218, 331}; /* * g723_24_encoder() * * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. * Returns -1 if invalid input coding value. */ int g723_24_encoder( int sl, G72x_STATE *state_ptr) { short sei, sezi, se, sez; /* ACCUM */ short d; /* SUBTA */ short y; /* MIX */ short sr; /* ADDB */ short dqsez; /* ADDC */ short dq, i; /* linearize input sample to 14-bit PCM */ sl >>= 2; /* sl of 14-bit dynamic range */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ d = sl - se; /* d = estimation diff. */ /* quantize prediction difference d */ y = step_size(state_ptr); /* quantizer step size */ i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ dq = reconstruct(i & 4, g723_24_dqlntab[i], y); /* quantized diff. */ sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ dqsez = sr + sez - se; /* pole prediction diff. */ update(3, y, g723_24_witab[i], g723_24_fitab[i], dq, sr, dqsez, state_ptr); return (i); } /* * g723_24_decoder() * * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns * the resulting 16-bit linear PCM, A-law or u-law sample value. * -1 is returned if the output coding is unknown. */ int g723_24_decoder( int i, G72x_STATE *state_ptr) { short sezi, sei, sez, se; /* ACCUM */ short y; /* MIX */ short sr; /* ADDB */ short dq; short dqsez; i &= 0x07; /* mask to get proper bits */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ y = step_size(state_ptr); /* adaptive quantizer step size */ dq = reconstruct(i & 0x04, g723_24_dqlntab[i], y); /* unquantize pred diff */ sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ dqsez = sr - se + sez; /* pole prediction diff. */ update(3, y, g723_24_witab[i], g723_24_fitab[i], dq, sr, dqsez, state_ptr); return (sr << 2); /* sr was of 14-bit dynamic range */ } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 75389236-650b-4427-98f3-0df6e8fb24bc */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * g723_40.c * * Description: * * g723_40_encoder(), g723_40_decoder() * * These routines comprise an implementation of the CCITT G.723 40Kbps * ADPCM coding algorithm. Essentially, this implementation is identical to * the bit level description except for a few deviations which * take advantage of workstation attributes, such as hardware 2's * complement arithmetic. * * The deviation from the bit level specification (lookup tables), * preserves the bit level performance specifications. * * As outlined in the G.723 Recommendation, the algorithm is broken * down into modules. Each section of code below is preceded by * the name of the module which it is implementing. * */ /* * Maps G.723_40 code word to ructeconstructed scale factor normalized log * magnitude values. */ static short g723_40_dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, 358, 395, 429, 459, 488, 514, 539, 566, 566, 539, 514, 488, 459, 429, 395, 358, 318, 274, 224, 169, 104, 28, -66, -2048}; /* Maps G.723_40 code word to log of scale factor multiplier. */ static short g723_40_witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; /* * Maps G.723_40 code words to a set of values whose long and short * term averages are computed and then compared to give an indication * how stationary (steady state) the signal is. */ static short g723_40_fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, 378, 413, 445, 475, 502, 528, 553}; /* * g723_40_encoder() * * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens * the resulting 5-bit CCITT G.723 40Kbps code. * Returns -1 if the input coding value is invalid. */ int g723_40_encoder (int sl, G72x_STATE *state_ptr) { short sei, sezi, se, sez; /* ACCUM */ short d; /* SUBTA */ short y; /* MIX */ short sr; /* ADDB */ short dqsez; /* ADDC */ short dq, i; /* linearize input sample to 14-bit PCM */ sl >>= 2; /* sl of 14-bit dynamic range */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ d = sl - se; /* d = estimation difference */ /* quantize prediction difference */ y = step_size(state_ptr); /* adaptive quantizer step size */ i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ dq = reconstruct(i & 0x10, g723_40_dqlntab[i], y); /* quantized diff */ sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ update(5, y, g723_40_witab[i], g723_40_fitab[i], dq, sr, dqsez, state_ptr); return (i); } /* * g723_40_decoder() * * Decodes a 5-bit CCITT G.723 40Kbps code and returns * the resulting 16-bit linear PCM, A-law or u-law sample value. * -1 is returned if the output coding is unknown. */ int g723_40_decoder (int i, G72x_STATE *state_ptr) { short sezi, sei, sez, se; /* ACCUM */ short y ; /* MIX */ short sr; /* ADDB */ short dq; short dqsez; i &= 0x1f; /* mask to get proper bits */ sezi = predictor_zero(state_ptr); sez = sezi >> 1; sei = sezi + predictor_pole(state_ptr); se = sei >> 1; /* se = estimated signal */ y = step_size(state_ptr); /* adaptive quantizer step size */ dq = reconstruct(i & 0x10, g723_40_dqlntab[i], y); /* estimation diff. */ sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ dqsez = sr - se + sez; /* pole prediction diff. */ update(5, y, g723_40_witab[i], g723_40_fitab[i], dq, sr, dqsez, state_ptr); return (sr << 2); /* sr was of 14-bit dynamic range */ } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: eb8d9a00-32bf-4dd2-b287-01b0336d72bf */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ /* * g72x.c * * Common routines for G.721 and G.723 conversions. */ #include #include #include static short power2 [15] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000 } ; /* * quan() * * quantizes the input val against the table of size short integers. * It returns i if table[i - 1] <= val < table[i]. * * Using linear search for simple coding. */ static int quan (int val, short *table, int size) { int i; for (i = 0; i < size; i++) if (val < *table++) break; return (i); } /* * fmult() * * returns the integer product of the 14-bit integer "an" and * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". */ static int fmult (int an, int srn) { short anmag, anexp, anmant; short wanexp, wanmant; short retval; anmag = (an > 0) ? an : ((-an) & 0x1FFF); anexp = quan(anmag, power2, 15) - 6; anmant = (anmag == 0) ? 32 : (anexp >= 0) ? anmag >> anexp : anmag << -anexp; wanexp = anexp + ((srn >> 6) & 0xF) - 13; /* ** The original was : ** wanmant = (anmant * (srn & 0x37) + 0x30) >> 4 ; ** but could see no valid reason for the + 0x30. ** Removed it and it improved the SNR of the codec. */ wanmant = (anmant * (srn & 0x37)) >> 4 ; retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : (wanmant >> -wanexp); return (((an ^ srn) < 0) ? -retval : retval); } /* * private_init_state() * * This routine initializes and/or resets the G72x_PRIVATE structure * pointed to by 'state_ptr'. * All the initial state values are specified in the CCITT G.721 document. */ void private_init_state (G72x_STATE *state_ptr) { int cnta; state_ptr->yl = 34816; state_ptr->yu = 544; state_ptr->dms = 0; state_ptr->dml = 0; state_ptr->ap = 0; for (cnta = 0; cnta < 2; cnta++) { state_ptr->a[cnta] = 0; state_ptr->pk[cnta] = 0; state_ptr->sr[cnta] = 32; } for (cnta = 0; cnta < 6; cnta++) { state_ptr->b[cnta] = 0; state_ptr->dq[cnta] = 32; } state_ptr->td = 0; } /* private_init_state */ int g72x_reader_init (G72x_DATA *data, int codec) { G72x_STATE *pstate ; if (sizeof (data->sprivateo) < sizeof (G72x_STATE)) { /* This is for safety only. */ return 1 ; } ; memset (data, 0, sizeof (G72x_DATA)) ; pstate = (G72x_STATE*) data->sprivateo ; private_init_state (pstate) ; pstate->encoder = NULL ; switch (codec) { case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */ pstate->decoder = g723_16_decoder ; data->blocksize = G723_16_BYTES_PER_BLOCK ; data->samplesperblock = G723_16_SAMPLES_PER_BLOCK ; pstate->codec_bits = 2 ; break ; case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */ pstate->decoder = g723_24_decoder ; data->blocksize = G723_24_BYTES_PER_BLOCK ; data->samplesperblock = G723_24_SAMPLES_PER_BLOCK ; pstate->codec_bits = 3 ; break ; case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */ pstate->decoder = g721_decoder ; data->blocksize = G721_32_BYTES_PER_BLOCK ; data->samplesperblock = G721_32_SAMPLES_PER_BLOCK ; pstate->codec_bits = 4 ; break ; case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */ pstate->decoder = g723_40_decoder ; data->blocksize = G721_40_BYTES_PER_BLOCK ; data->samplesperblock = G721_40_SAMPLES_PER_BLOCK ; pstate->codec_bits = 5 ; break ; default : return 1 ; } ; return 0 ; } /* g72x_reader_init */ int g72x_writer_init (G72x_DATA *data, int codec) { G72x_STATE *pstate ; if (sizeof (data->sprivateo) < sizeof (G72x_STATE)) { /* This is for safety only. Gets optimised out. */ return 1 ; } ; memset (data, 0, sizeof (G72x_DATA)) ; pstate = (G72x_STATE*) data->sprivateo ; private_init_state (pstate) ; pstate->decoder = NULL ; switch (codec) { case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */ pstate->encoder = g723_16_encoder ; data->blocksize = G723_16_BYTES_PER_BLOCK ; data->samplesperblock = G723_16_SAMPLES_PER_BLOCK ; pstate->codec_bits = 2 ; break ; case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */ pstate->encoder = g723_24_encoder ; data->blocksize = G723_24_BYTES_PER_BLOCK ; data->samplesperblock = G723_24_SAMPLES_PER_BLOCK ; pstate->codec_bits = 3 ; break ; case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */ pstate->encoder = g721_encoder ; data->blocksize = G721_32_BYTES_PER_BLOCK ; data->samplesperblock = G721_32_SAMPLES_PER_BLOCK ; pstate->codec_bits = 4 ; break ; case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */ pstate->encoder = g723_40_encoder ; data->blocksize = G721_40_BYTES_PER_BLOCK ; data->samplesperblock = G721_40_SAMPLES_PER_BLOCK ; pstate->codec_bits = 5 ; break ; default : return 1 ; } ; return 0 ; } /* g72x_writer_init */ int unpack_bytes (G72x_DATA *data, int bits) { unsigned int in_buffer = 0 ; unsigned char in_byte ; int k, in_bits = 0, bindex = 0 ; for (k = 0 ; bindex <= data->blocksize && k < G72x_BLOCK_SIZE ; k++) { if (in_bits < bits) { in_byte = data->block [bindex++] ; in_buffer |= (in_byte << in_bits); in_bits += 8; } data->samples [k] = in_buffer & ((1 << bits) - 1); in_buffer >>= bits; in_bits -= bits; } ; return k ; } /* unpack_bytes */ int g72x_decode_block (G72x_DATA *data) { G72x_STATE *pstate ; int k, count ; pstate = (G72x_STATE*) data->sprivateo ; count = unpack_bytes (data, pstate->codec_bits) ; for (k = 0 ; k < count ; k++) data->samples [k] = pstate->decoder (data->samples [k], pstate) ; return 0 ; } /* g72x_decode_block */ int pack_bytes (G72x_DATA *data, int bits) { unsigned int out_buffer = 0 ; int k, bindex = 0, out_bits = 0 ; unsigned char out_byte ; for (k = 0 ; k < G72x_BLOCK_SIZE ; k++) { out_buffer |= (data->samples [k] << out_bits) ; out_bits += bits ; if (out_bits >= 8) { out_byte = out_buffer & 0xFF ; out_bits -= 8 ; out_buffer >>= 8 ; data->block [bindex++] = out_byte ; } } ; return bindex ; } /* pack_bytes */ int g72x_encode_block (G72x_DATA *data) { G72x_STATE *pstate ; int k, count ; pstate = (G72x_STATE*) data->sprivateo ; for (k = 0 ; k < data->samplesperblock ; k++) data->samples [k] = pstate->encoder (data->samples [k], pstate) ; count = pack_bytes (data, pstate->codec_bits) ; return count ; } /* g72x_encode_block */ /* * predictor_zero() * * computes the estimated signal from 6-zero predictor. * */ int predictor_zero (G72x_STATE *state_ptr) { int i; int sezi; sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); for (i = 1; i < 6; i++) /* ACCUM */ sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); return (sezi); } /* * predictor_pole() * * computes the estimated signal from 2-pole predictor. * */ int predictor_pole(G72x_STATE *state_ptr) { return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); } /* * step_size() * * computes the quantization step size of the adaptive quantizer. * */ int step_size (G72x_STATE *state_ptr) { int y; int dif; int al; if (state_ptr->ap >= 256) return (state_ptr->yu); else { y = state_ptr->yl >> 6; dif = state_ptr->yu - y; al = state_ptr->ap >> 2; if (dif > 0) y += (dif * al) >> 6; else if (dif < 0) y += (dif * al + 0x3F) >> 6; return (y); } } /* * quantize() * * Given a raw sample, 'd', of the difference signal and a * quantization step size scale factor, 'y', this routine returns the * ADPCM codeword to which that sample gets quantized. The step * size scale factor division operation is done in the log base 2 domain * as a subtraction. */ int quantize( int d, /* Raw difference signal sample */ int y, /* Step size multiplier */ short *table, /* quantization table */ int size) /* table size of short integers */ { short dqm; /* Magnitude of 'd' */ short expon; /* Integer part of base 2 log of 'd' */ short mant; /* Fractional part of base 2 log */ short dl; /* Log of magnitude of 'd' */ short dln; /* Step size scale factor normalized log */ int i; /* * LOG * * Compute base 2 log of 'd', and store in 'dl'. */ dqm = abs(d); expon = quan(dqm >> 1, power2, 15); mant = ((dqm << 7) >> expon) & 0x7F; /* Fractional portion. */ dl = (expon << 7) + mant; /* * SUBTB * * "Divide" by step size multiplier. */ dln = dl - (y >> 2); /* * QUAN * * Obtain codword i for 'd'. */ i = quan(dln, table, size); if (d < 0) /* take 1's complement of i */ return ((size << 1) + 1 - i); else if (i == 0) /* take 1's complement of 0 */ return ((size << 1) + 1); /* new in 1988 */ else return (i); } /* * reconstruct() * * Returns reconstructed difference signal 'dq' obtained from * codeword 'i' and quantization step size scale factor 'y'. * Multiplication is performed in log base 2 domain as addition. */ int reconstruct( int sign, /* 0 for non-negative value */ int dqln, /* G.72x codeword */ int y) /* Step size multiplier */ { short dql; /* Log of 'dq' magnitude */ short dex; /* Integer part of log */ short dqt; short dq; /* Reconstructed difference signal sample */ dql = dqln + (y >> 2); /* ADDA */ if (dql < 0) { return ((sign) ? -0x8000 : 0); } else { /* ANTILOG */ dex = (dql >> 7) & 15; dqt = 128 + (dql & 127); dq = (dqt << 7) >> (14 - dex); return ((sign) ? (dq - 0x8000) : dq); } } /* * update() * * updates the state variables for each output code */ void update( int code_size, /* distinguish 723_40 with others */ int y, /* quantizer step size */ int wi, /* scale factor multiplier */ int fi, /* for long/short term energies */ int dq, /* quantized prediction difference */ int sr, /* reconstructed signal */ int dqsez, /* difference from 2-pole predictor */ G72x_STATE *state_ptr) /* coder state pointer */ { int cnt; short mag, expon; /* Adaptive predictor, FLOAT A */ short a2p = 0; /* LIMC */ short a1ul; /* UPA1 */ short pks1; /* UPA2 */ short fa1; char tr; /* tone/transition detector */ short ylint, thr2, dqthr; short ylfrac, thr1; short pk0; pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ mag = dq & 0x7FFF; /* prediction difference magnitude */ /* TRANS */ ylint = state_ptr->yl >> 15; /* exponent part of yl */ ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ thr1 = (32 + ylfrac) << ylint; /* threshold */ thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ if (state_ptr->td == 0) /* signal supposed voice */ tr = 0; else if (mag <= dqthr) /* supposed data, but small mag */ tr = 0; /* treated as voice */ else /* signal is data (modem) */ tr = 1; /* * Quantizer scale factor adaptation. */ /* FUNCTW & FILTD & DELAY */ /* update non-steady state step size multiplier */ state_ptr->yu = y + ((wi - y) >> 5); /* LIMB */ if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ state_ptr->yu = 544; else if (state_ptr->yu > 5120) state_ptr->yu = 5120; /* FILTE & DELAY */ /* update steady state step size multiplier */ state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); /* * Adaptive predictor coefficients. */ if (tr == 1) { /* reset a's and b's for modem signal */ state_ptr->a[0] = 0; state_ptr->a[1] = 0; state_ptr->b[0] = 0; state_ptr->b[1] = 0; state_ptr->b[2] = 0; state_ptr->b[3] = 0; state_ptr->b[4] = 0; state_ptr->b[5] = 0; } else { /* update a's and b's */ pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ /* update predictor pole a[1] */ a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); if (dqsez != 0) { fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; if (fa1 < -8191) /* a2p = function of fa1 */ a2p -= 0x100; else if (fa1 > 8191) a2p += 0xFF; else a2p += fa1 >> 5; if (pk0 ^ state_ptr->pk[1]) { /* LIMC */ if (a2p <= -12160) a2p = -12288; else if (a2p >= 12416) a2p = 12288; else a2p -= 0x80; } else if (a2p <= -12416) a2p = -12288; else if (a2p >= 12160) a2p = 12288; else a2p += 0x80; } /* TRIGB & DELAY */ state_ptr->a[1] = a2p; /* UPA1 */ /* update predictor pole a[0] */ state_ptr->a[0] -= state_ptr->a[0] >> 8; if (dqsez != 0) { if (pks1 == 0) state_ptr->a[0] += 192; else state_ptr->a[0] -= 192; } ; /* LIMD */ a1ul = 15360 - a2p; if (state_ptr->a[0] < -a1ul) state_ptr->a[0] = -a1ul; else if (state_ptr->a[0] > a1ul) state_ptr->a[0] = a1ul; /* UPB : update predictor zeros b[6] */ for (cnt = 0; cnt < 6; cnt++) { if (code_size == 5) /* for 40Kbps G.723 */ state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; else /* for G.721 and 24Kbps G.723 */ state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; if (dq & 0x7FFF) { /* XOR */ if ((dq ^ state_ptr->dq[cnt]) >= 0) state_ptr->b[cnt] += 128; else state_ptr->b[cnt] -= 128; } } } for (cnt = 5; cnt > 0; cnt--) state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ if (mag == 0) { state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; } else { expon = quan(mag, power2, 15); state_ptr->dq[0] = (dq >= 0) ? (expon << 6) + ((mag << 6) >> expon) : (expon << 6) + ((mag << 6) >> expon) - 0x400; } state_ptr->sr[1] = state_ptr->sr[0]; /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ if (sr == 0) { state_ptr->sr[0] = 0x20; } else if (sr > 0) { expon = quan(sr, power2, 15); state_ptr->sr[0] = (expon << 6) + ((sr << 6) >> expon); } else if (sr > -32768) { mag = -sr; expon = quan(mag, power2, 15); state_ptr->sr[0] = (expon << 6) + ((mag << 6) >> expon) - 0x400; } else state_ptr->sr[0] = (short) 0xFC20; /* DELAY A */ state_ptr->pk[1] = state_ptr->pk[0]; state_ptr->pk[0] = pk0; /* TONE */ if (tr == 1) /* this sample has been treated as data */ state_ptr->td = 0; /* next one will be treated as voice */ else if (a2p < -11776) /* small sample-to-sample correlation */ state_ptr->td = 1; /* signal may be data */ else /* signal is voice */ state_ptr->td = 0; /* * Adaptation speed control. */ state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ if (tr == 1) state_ptr->ap = 256; else if (y < 1536) /* SUBTC */ state_ptr->ap += (0x200 - state_ptr->ap) >> 4; else if (state_ptr->td == 1) state_ptr->ap += (0x200 - state_ptr->ap) >> 4; else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= (state_ptr->dml >> 3)) state_ptr->ap += (0x200 - state_ptr->ap) >> 4; else state_ptr->ap += (-state_ptr->ap) >> 4; return ; } /* update */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 6298dc75-fd0f-4062-9b90-f73ed69f22d4 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #define GSM610_BLOCKSIZE 33 #define GSM610_SAMPLES 160 typedef struct gsm610_tag { int blocks ; int blockcount, samplecount ; int samplesperblock, blocksize ; int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ; int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ; short samples [WAV_W64_GSM610_SAMPLES] ; unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ; gsm gsm_data ; } GSM610_PRIVATE ; static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t gsm610_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t gsm610_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t gsm610_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t gsm610_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ; static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ; static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ; static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int gsm610_close (SF_PRIVATE *psf) ; /*============================================================================================ ** WAV GSM610 initialisation function. */ int gsm610_init (SF_PRIVATE *psf) { GSM610_PRIVATE *pgsm610 ; int true_flag = 1 ; if (psf->mode == SFM_RDWR) return SFE_BAD_MODE_RW ; psf->sf.seekable = SF_FALSE ; if (! (pgsm610 = malloc (sizeof (GSM610_PRIVATE)))) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pgsm610 ; memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ; /*============================================================ Need separate gsm_data structs for encode and decode. ============================================================*/ if (! (pgsm610->gsm_data = gsm_create ())) return SFE_MALLOC_FAILED ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV || (psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_W64) { gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ; pgsm610->encode_block = gsm610_wav_encode_block ; pgsm610->decode_block = gsm610_wav_decode_block ; pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ; pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ; } else { pgsm610->encode_block = gsm610_encode_block ; pgsm610->decode_block = gsm610_decode_block ; pgsm610->samplesperblock = GSM610_SAMPLES ; pgsm610->blocksize = GSM610_BLOCKSIZE ; } ; if (psf->mode == SFM_READ) { if (psf->datalength % pgsm610->blocksize) { psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ; pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ; } else pgsm610->blocks = psf->datalength / pgsm610->blocksize ; psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ; pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */ psf->read_short = gsm610_read_s ; psf->read_int = gsm610_read_i ; psf->read_float = gsm610_read_f ; psf->read_double = gsm610_read_d ; } ; if (psf->mode == SFM_WRITE) { pgsm610->blockcount = 0 ; pgsm610->samplecount = 0 ; psf->write_short = gsm610_write_s ; psf->write_int = gsm610_write_i ; psf->write_float = gsm610_write_f ; psf->write_double = gsm610_write_d ; } ; psf->close = gsm610_close ; psf->seek = gsm610_seek ; psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; return 0 ; } /* gsm610_init */ /*============================================================================================ ** GSM 6.10 Read Functions. */ static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) { int k ; pgsm610->blockcount ++ ; pgsm610->samplecount = 0 ; if (pgsm610->blockcount > pgsm610->blocks) { memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; return 1 ; } ; if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ; if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ; return 0 ; } ; if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0) { psf_log_printf (psf, "Error from gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ; return 0 ; } ; return 1 ; } /* gsm610_wav_decode_block */ static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) { int k ; pgsm610->blockcount ++ ; pgsm610->samplecount = 0 ; if (pgsm610->blockcount > pgsm610->blocks) { memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ; return 1 ; } ; if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ; if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0) { psf_log_printf (psf, "Error from gsm_decode() on frame : %d\n", pgsm610->blockcount) ; return 0 ; } ; return 1 ; } /* gsm610_decode_block */ static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock) { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; return total ; } ; if (pgsm610->samplecount >= pgsm610->samplesperblock) pgsm610->decode_block (psf, pgsm610) ; count = pgsm610->samplesperblock - pgsm610->samplecount ; count = (len - indx > count) ? count : len - indx ; memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ; indx += count ; pgsm610->samplecount += count ; total = indx ; } ; return total ; } /* gsm610_read_block */ static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x1000000 : (int) len ; count = gsm610_read_block (psf, pgsm610, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* gsm610_read_s */ static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = sptr [k] << 16 ; total += count ; len -= readcount ; } ; return total ; } /* gsm610_read_i */ static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* gsm610_read_f */ static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = gsm610_read_block (psf, pgsm610, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * sptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* gsm610_read_d */ static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { GSM610_PRIVATE *pgsm610 ; int newblock, newsample ; mode = mode ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; if (psf->dataoffset < 0) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (offset == 0) { int true_flag = 1 ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; pgsm610->blockcount = 0 ; gsm_init (pgsm610->gsm_data) ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV || (psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_W64) gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ; pgsm610->decode_block (psf, pgsm610) ; pgsm610->samplecount = 0 ; return 0 ; } ; if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; newblock = offset / pgsm610->samplesperblock ; newsample = offset % pgsm610->samplesperblock ; if (psf->mode == SFM_READ) { if (psf->read_current != newblock * pgsm610->samplesperblock + newsample) { psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ; pgsm610->blockcount = newblock ; pgsm610->decode_block (psf, pgsm610) ; pgsm610->samplecount = newsample ; } ; return newblock * pgsm610->samplesperblock + newsample ; } ; /* What to do about write??? */ psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } /* gsm610_seek */ /*========================================================================================== ** GSM 6.10 Write Functions. */ static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) { int k ; /* Encode the samples. */ gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; /* Write the block to disk. */ if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ; pgsm610->samplecount = 0 ; pgsm610->blockcount ++ ; /* Set samples to zero for next block. */ memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; return 1 ; } /* gsm610_encode_block */ static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) { int k ; /* Encode the samples. */ gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ; gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ; /* Write the block to disk. */ if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ; pgsm610->samplecount = 0 ; pgsm610->blockcount ++ ; /* Set samples to zero for next block. */ memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ; return 1 ; } /* gsm610_wav_encode_block */ static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { count = pgsm610->samplesperblock - pgsm610->samplecount ; if (count > len - indx) count = len - indx ; memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ; indx += count ; pgsm610->samplecount += count ; total = indx ; if (pgsm610->samplecount >= pgsm610->samplesperblock) pgsm610->encode_block (psf, pgsm610) ; } ; return total ; } /* gsm610_write_block */ static sf_count_t gsm610_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = gsm610_write_block (psf, pgsm610, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* gsm610_write_s */ static sf_count_t gsm610_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* gsm610_write_i */ static sf_count_t gsm610_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrintf (normfact * ptr [total + k]) ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* gsm610_write_f */ static sf_count_t gsm610_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { GSM610_PRIVATE *pgsm610 ; short *sptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrint (normfact * ptr [total + k]) ; count = gsm610_write_block (psf, pgsm610, sptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* gsm610_write_d */ static int gsm610_close (SF_PRIVATE *psf) { GSM610_PRIVATE *pgsm610 ; if (! psf->fdata) return 0 ; pgsm610 = (GSM610_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE) { /* If a block has been partially assembled, write it out ** as the final block. */ if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock) pgsm610->encode_block (psf, pgsm610) ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; } ; if (pgsm610->gsm_data) gsm_destroy (pgsm610->gsm_data) ; return 0 ; } /* gsm610_close */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 8575187d-af4f-4acf-b9dd-6ff705628345 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include #include gsm gsm_create (void) { gsm r; r = malloc (sizeof(struct gsm_state)); if (!r) return r; memset((char *)r, 0, sizeof (struct gsm_state)); r->nrp = 40; return r; } /* Added for libsndfile : May 6, 2002. Not sure if it works. */ void gsm_init (gsm state) { memset (state, 0, sizeof (struct gsm_state)) ; state->nrp = 40 ; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 9fedb6b3-ed99-40c2-aac1-484c536261fe */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ int gsm_decode (gsm s, gsm_byte * c, gsm_signal * target) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; #ifdef WAV49 if (s->wav_fmt) { uword sr = 0; s->frame_index = !s->frame_index; if (s->frame_index) { sr = *c++; LARc[0] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 2; LARc[1] = sr & 0x3f; sr >>= 6; sr |= (uword)*c++ << 4; LARc[2] = sr & 0x1f; sr >>= 5; LARc[3] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 2; LARc[4] = sr & 0xf; sr >>= 4; LARc[5] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; /* 5 */ LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[0] = sr & 0x7f; sr >>= 7; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; sr = *c++; xmc[1] = sr & 0x7; sr >>= 3; xmc[2] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; xmc[5] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 10 */ xmc[6] = sr & 0x7; sr >>= 3; xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; sr = *c++; xmc[9] = sr & 0x7; sr >>= 3; xmc[10] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[1] = sr & 0x7f; sr >>= 7; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; sr = *c++; /* 15 */ xmc[14] = sr & 0x7; sr >>= 3; xmc[15] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; xmc[18] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[19] = sr & 0x7; sr >>= 3; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; sr = *c++; xmc[22] = sr & 0x7; sr >>= 3; xmc[23] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; /* 20 */ Nc[2] = sr & 0x7f; sr >>= 7; bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; sr = *c++; xmc[27] = sr & 0x7; sr >>= 3; xmc[28] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; xmc[31] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[32] = sr & 0x7; sr >>= 3; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; sr = *c++; /* 25 */ xmc[35] = sr & 0x7; sr >>= 3; xmc[36] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 4; Nc[3] = sr & 0x7f; sr >>= 7; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 1; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; sr = *c++; xmc[40] = sr & 0x7; sr >>= 3; xmc[41] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 30 */ xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; xmc[44] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[45] = sr & 0x7; sr >>= 3; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; sr = *c++; xmc[48] = sr & 0x7; sr >>= 3; xmc[49] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; s->frame_chain = sr & 0xf; } else { sr = s->frame_chain; sr |= (uword)*c++ << 4; /* 1 */ LARc[0] = sr & 0x3f; sr >>= 6; LARc[1] = sr & 0x3f; sr >>= 6; sr = *c++; LARc[2] = sr & 0x1f; sr >>= 5; sr |= (uword)*c++ << 3; LARc[3] = sr & 0x1f; sr >>= 5; LARc[4] = sr & 0xf; sr >>= 4; sr |= (uword)*c++ << 2; LARc[5] = sr & 0xf; sr >>= 4; LARc[6] = sr & 0x7; sr >>= 3; LARc[7] = sr & 0x7; sr >>= 3; sr = *c++; /* 5 */ Nc[0] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[0] = sr & 0x3; sr >>= 2; Mc[0] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[0] = sr & 0x3f; sr >>= 6; xmc[0] = sr & 0x7; sr >>= 3; xmc[1] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[2] = sr & 0x7; sr >>= 3; xmc[3] = sr & 0x7; sr >>= 3; xmc[4] = sr & 0x7; sr >>= 3; sr = *c++; xmc[5] = sr & 0x7; sr >>= 3; xmc[6] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; /* 10 */ xmc[7] = sr & 0x7; sr >>= 3; xmc[8] = sr & 0x7; sr >>= 3; xmc[9] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[10] = sr & 0x7; sr >>= 3; xmc[11] = sr & 0x7; sr >>= 3; xmc[12] = sr & 0x7; sr >>= 3; sr = *c++; Nc[1] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[1] = sr & 0x3; sr >>= 2; Mc[1] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[1] = sr & 0x3f; sr >>= 6; xmc[13] = sr & 0x7; sr >>= 3; xmc[14] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 15 */ xmc[15] = sr & 0x7; sr >>= 3; xmc[16] = sr & 0x7; sr >>= 3; xmc[17] = sr & 0x7; sr >>= 3; sr = *c++; xmc[18] = sr & 0x7; sr >>= 3; xmc[19] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[20] = sr & 0x7; sr >>= 3; xmc[21] = sr & 0x7; sr >>= 3; xmc[22] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[23] = sr & 0x7; sr >>= 3; xmc[24] = sr & 0x7; sr >>= 3; xmc[25] = sr & 0x7; sr >>= 3; sr = *c++; Nc[2] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; /* 20 */ bc[2] = sr & 0x3; sr >>= 2; Mc[2] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[2] = sr & 0x3f; sr >>= 6; xmc[26] = sr & 0x7; sr >>= 3; xmc[27] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[28] = sr & 0x7; sr >>= 3; xmc[29] = sr & 0x7; sr >>= 3; xmc[30] = sr & 0x7; sr >>= 3; sr = *c++; xmc[31] = sr & 0x7; sr >>= 3; xmc[32] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[33] = sr & 0x7; sr >>= 3; xmc[34] = sr & 0x7; sr >>= 3; xmc[35] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; /* 25 */ xmc[36] = sr & 0x7; sr >>= 3; xmc[37] = sr & 0x7; sr >>= 3; xmc[38] = sr & 0x7; sr >>= 3; sr = *c++; Nc[3] = sr & 0x7f; sr >>= 7; sr |= (uword)*c++ << 1; bc[3] = sr & 0x3; sr >>= 2; Mc[3] = sr & 0x3; sr >>= 2; sr |= (uword)*c++ << 5; xmaxc[3] = sr & 0x3f; sr >>= 6; xmc[39] = sr & 0x7; sr >>= 3; xmc[40] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[41] = sr & 0x7; sr >>= 3; xmc[42] = sr & 0x7; sr >>= 3; xmc[43] = sr & 0x7; sr >>= 3; sr = *c++; /* 30 */ xmc[44] = sr & 0x7; sr >>= 3; xmc[45] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 2; xmc[46] = sr & 0x7; sr >>= 3; xmc[47] = sr & 0x7; sr >>= 3; xmc[48] = sr & 0x7; sr >>= 3; sr |= (uword)*c++ << 1; xmc[49] = sr & 0x7; sr >>= 3; xmc[50] = sr & 0x7; sr >>= 3; xmc[51] = sr & 0x7; sr >>= 3; } } else #endif { /* GSM_MAGIC = (*c >> 4) & 0xF; */ if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1; LARc[0] = (*c++ & 0xF) << 2; /* 1 */ LARc[0] |= (*c >> 6) & 0x3; LARc[1] = *c++ & 0x3F; LARc[2] = (*c >> 3) & 0x1F; LARc[3] = (*c++ & 0x7) << 2; LARc[3] |= (*c >> 6) & 0x3; LARc[4] = (*c >> 2) & 0xF; LARc[5] = (*c++ & 0x3) << 2; LARc[5] |= (*c >> 6) & 0x3; LARc[6] = (*c >> 3) & 0x7; LARc[7] = *c++ & 0x7; Nc[0] = (*c >> 1) & 0x7F; bc[0] = (*c++ & 0x1) << 1; bc[0] |= (*c >> 7) & 0x1; Mc[0] = (*c >> 5) & 0x3; xmaxc[0] = (*c++ & 0x1F) << 1; xmaxc[0] |= (*c >> 7) & 0x1; xmc[0] = (*c >> 4) & 0x7; xmc[1] = (*c >> 1) & 0x7; xmc[2] = (*c++ & 0x1) << 2; xmc[2] |= (*c >> 6) & 0x3; xmc[3] = (*c >> 3) & 0x7; xmc[4] = *c++ & 0x7; xmc[5] = (*c >> 5) & 0x7; xmc[6] = (*c >> 2) & 0x7; xmc[7] = (*c++ & 0x3) << 1; /* 10 */ xmc[7] |= (*c >> 7) & 0x1; xmc[8] = (*c >> 4) & 0x7; xmc[9] = (*c >> 1) & 0x7; xmc[10] = (*c++ & 0x1) << 2; xmc[10] |= (*c >> 6) & 0x3; xmc[11] = (*c >> 3) & 0x7; xmc[12] = *c++ & 0x7; Nc[1] = (*c >> 1) & 0x7F; bc[1] = (*c++ & 0x1) << 1; bc[1] |= (*c >> 7) & 0x1; Mc[1] = (*c >> 5) & 0x3; xmaxc[1] = (*c++ & 0x1F) << 1; xmaxc[1] |= (*c >> 7) & 0x1; xmc[13] = (*c >> 4) & 0x7; xmc[14] = (*c >> 1) & 0x7; xmc[15] = (*c++ & 0x1) << 2; xmc[15] |= (*c >> 6) & 0x3; xmc[16] = (*c >> 3) & 0x7; xmc[17] = *c++ & 0x7; xmc[18] = (*c >> 5) & 0x7; xmc[19] = (*c >> 2) & 0x7; xmc[20] = (*c++ & 0x3) << 1; xmc[20] |= (*c >> 7) & 0x1; xmc[21] = (*c >> 4) & 0x7; xmc[22] = (*c >> 1) & 0x7; xmc[23] = (*c++ & 0x1) << 2; xmc[23] |= (*c >> 6) & 0x3; xmc[24] = (*c >> 3) & 0x7; xmc[25] = *c++ & 0x7; Nc[2] = (*c >> 1) & 0x7F; bc[2] = (*c++ & 0x1) << 1; /* 20 */ bc[2] |= (*c >> 7) & 0x1; Mc[2] = (*c >> 5) & 0x3; xmaxc[2] = (*c++ & 0x1F) << 1; xmaxc[2] |= (*c >> 7) & 0x1; xmc[26] = (*c >> 4) & 0x7; xmc[27] = (*c >> 1) & 0x7; xmc[28] = (*c++ & 0x1) << 2; xmc[28] |= (*c >> 6) & 0x3; xmc[29] = (*c >> 3) & 0x7; xmc[30] = *c++ & 0x7; xmc[31] = (*c >> 5) & 0x7; xmc[32] = (*c >> 2) & 0x7; xmc[33] = (*c++ & 0x3) << 1; xmc[33] |= (*c >> 7) & 0x1; xmc[34] = (*c >> 4) & 0x7; xmc[35] = (*c >> 1) & 0x7; xmc[36] = (*c++ & 0x1) << 2; xmc[36] |= (*c >> 6) & 0x3; xmc[37] = (*c >> 3) & 0x7; xmc[38] = *c++ & 0x7; Nc[3] = (*c >> 1) & 0x7F; bc[3] = (*c++ & 0x1) << 1; bc[3] |= (*c >> 7) & 0x1; Mc[3] = (*c >> 5) & 0x3; xmaxc[3] = (*c++ & 0x1F) << 1; xmaxc[3] |= (*c >> 7) & 0x1; xmc[39] = (*c >> 4) & 0x7; xmc[40] = (*c >> 1) & 0x7; xmc[41] = (*c++ & 0x1) << 2; xmc[41] |= (*c >> 6) & 0x3; xmc[42] = (*c >> 3) & 0x7; xmc[43] = *c++ & 0x7; /* 30 */ xmc[44] = (*c >> 5) & 0x7; xmc[45] = (*c >> 2) & 0x7; xmc[46] = (*c++ & 0x3) << 1; xmc[46] |= (*c >> 7) & 0x1; xmc[47] = (*c >> 4) & 0x7; xmc[48] = (*c >> 1) & 0x7; xmc[49] = (*c++ & 0x1) << 2; xmc[49] |= (*c >> 6) & 0x3; xmc[50] = (*c >> 3) & 0x7; xmc[51] = *c & 0x7; /* 33 */ } Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target); return 0; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 6a9b6628-821c-4a96-84c1-485ebd35f170 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #ifdef HAS_STDLIB_H # include #else # ifdef HAS_MALLOC_H # include # else extern void free(); # endif #endif void gsm_destroy (gsm S) { if (S) free((char *)S); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: f423d09b-6ccc-47e0-9b18-ee1cf7a8e473 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ void gsm_encode (gsm s, gsm_signal * source, gsm_byte * c) { word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4]; Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc); /* variable size GSM_MAGIC 4 LARc[0] 6 LARc[1] 6 LARc[2] 5 LARc[3] 5 LARc[4] 4 LARc[5] 4 LARc[6] 3 LARc[7] 3 Nc[0] 7 bc[0] 2 Mc[0] 2 xmaxc[0] 6 xmc[0] 3 xmc[1] 3 xmc[2] 3 xmc[3] 3 xmc[4] 3 xmc[5] 3 xmc[6] 3 xmc[7] 3 xmc[8] 3 xmc[9] 3 xmc[10] 3 xmc[11] 3 xmc[12] 3 Nc[1] 7 bc[1] 2 Mc[1] 2 xmaxc[1] 6 xmc[13] 3 xmc[14] 3 xmc[15] 3 xmc[16] 3 xmc[17] 3 xmc[18] 3 xmc[19] 3 xmc[20] 3 xmc[21] 3 xmc[22] 3 xmc[23] 3 xmc[24] 3 xmc[25] 3 Nc[2] 7 bc[2] 2 Mc[2] 2 xmaxc[2] 6 xmc[26] 3 xmc[27] 3 xmc[28] 3 xmc[29] 3 xmc[30] 3 xmc[31] 3 xmc[32] 3 xmc[33] 3 xmc[34] 3 xmc[35] 3 xmc[36] 3 xmc[37] 3 xmc[38] 3 Nc[3] 7 bc[3] 2 Mc[3] 2 xmaxc[3] 6 xmc[39] 3 xmc[40] 3 xmc[41] 3 xmc[42] 3 xmc[43] 3 xmc[44] 3 xmc[45] 3 xmc[46] 3 xmc[47] 3 xmc[48] 3 xmc[49] 3 xmc[50] 3 xmc[51] 3 */ #ifdef WAV49 if (s->wav_fmt) { s->frame_index = !s->frame_index; if (s->frame_index) { uword sr; sr = 0; sr = sr >> 6 | LARc[0] << 10; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 4; sr = sr >> 5 | LARc[2] << 11; *c++ = sr >> 7; sr = sr >> 5 | LARc[3] << 11; sr = sr >> 4 | LARc[4] << 12; *c++ = sr >> 6; sr = sr >> 4 | LARc[5] << 12; sr = sr >> 3 | LARc[6] << 13; *c++ = sr >> 7; sr = sr >> 3 | LARc[7] << 13; sr = sr >> 7 | Nc[0] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[0] << 14; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[0] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; sr = sr >> 3 | xmc[3] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[4] << 13; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[7] << 13; sr = sr >> 3 | xmc[8] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; sr = sr >> 3 | xmc[11] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[12] << 13; sr = sr >> 7 | Nc[1] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[1] << 14; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[13] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; sr = sr >> 3 | xmc[16] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[17] << 13; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[20] << 13; sr = sr >> 3 | xmc[21] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; sr = sr >> 3 | xmc[24] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[25] << 13; sr = sr >> 7 | Nc[2] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[2] << 14; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[26] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; sr = sr >> 3 | xmc[29] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[30] << 13; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[33] << 13; sr = sr >> 3 | xmc[34] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; sr = sr >> 3 | xmc[37] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[38] << 13; sr = sr >> 7 | Nc[3] << 9; *c++ = sr >> 5; sr = sr >> 2 | bc[3] << 14; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 3; sr = sr >> 3 | xmc[39] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; sr = sr >> 3 | xmc[42] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[43] << 13; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[46] << 13; sr = sr >> 3 | xmc[47] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; sr = sr >> 3 | xmc[50] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[51] << 13; sr = sr >> 4; *c = sr >> 8; s->frame_chain = *c; } else { uword sr; sr = 0; sr = sr >> 4 | s->frame_chain << 12; sr = sr >> 6 | LARc[0] << 10; *c++ = sr >> 6; sr = sr >> 6 | LARc[1] << 10; *c++ = sr >> 8; sr = sr >> 5 | LARc[2] << 11; sr = sr >> 5 | LARc[3] << 11; *c++ = sr >> 6; sr = sr >> 4 | LARc[4] << 12; sr = sr >> 4 | LARc[5] << 12; *c++ = sr >> 6; sr = sr >> 3 | LARc[6] << 13; sr = sr >> 3 | LARc[7] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[0] << 9; sr = sr >> 2 | bc[0] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[0] << 14; sr = sr >> 6 | xmaxc[0] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[0] << 13; sr = sr >> 3 | xmc[1] << 13; sr = sr >> 3 | xmc[2] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[3] << 13; sr = sr >> 3 | xmc[4] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[5] << 13; sr = sr >> 3 | xmc[6] << 13; sr = sr >> 3 | xmc[7] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[8] << 13; sr = sr >> 3 | xmc[9] << 13; sr = sr >> 3 | xmc[10] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[11] << 13; sr = sr >> 3 | xmc[12] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[1] << 9; sr = sr >> 2 | bc[1] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[1] << 14; sr = sr >> 6 | xmaxc[1] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[13] << 13; sr = sr >> 3 | xmc[14] << 13; sr = sr >> 3 | xmc[15] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[16] << 13; sr = sr >> 3 | xmc[17] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[18] << 13; sr = sr >> 3 | xmc[19] << 13; sr = sr >> 3 | xmc[20] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[21] << 13; sr = sr >> 3 | xmc[22] << 13; sr = sr >> 3 | xmc[23] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[24] << 13; sr = sr >> 3 | xmc[25] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[2] << 9; sr = sr >> 2 | bc[2] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[2] << 14; sr = sr >> 6 | xmaxc[2] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[26] << 13; sr = sr >> 3 | xmc[27] << 13; sr = sr >> 3 | xmc[28] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[29] << 13; sr = sr >> 3 | xmc[30] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[31] << 13; sr = sr >> 3 | xmc[32] << 13; sr = sr >> 3 | xmc[33] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[34] << 13; sr = sr >> 3 | xmc[35] << 13; sr = sr >> 3 | xmc[36] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[37] << 13; sr = sr >> 3 | xmc[38] << 13; *c++ = sr >> 8; sr = sr >> 7 | Nc[3] << 9; sr = sr >> 2 | bc[3] << 14; *c++ = sr >> 7; sr = sr >> 2 | Mc[3] << 14; sr = sr >> 6 | xmaxc[3] << 10; *c++ = sr >> 7; sr = sr >> 3 | xmc[39] << 13; sr = sr >> 3 | xmc[40] << 13; sr = sr >> 3 | xmc[41] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[42] << 13; sr = sr >> 3 | xmc[43] << 13; *c++ = sr >> 8; sr = sr >> 3 | xmc[44] << 13; sr = sr >> 3 | xmc[45] << 13; sr = sr >> 3 | xmc[46] << 13; *c++ = sr >> 7; sr = sr >> 3 | xmc[47] << 13; sr = sr >> 3 | xmc[48] << 13; sr = sr >> 3 | xmc[49] << 13; *c++ = sr >> 6; sr = sr >> 3 | xmc[50] << 13; sr = sr >> 3 | xmc[51] << 13; *c++ = sr >> 8; } } else #endif /* WAV49 */ { *c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */ | ((LARc[0] >> 2) & 0xF); *c++ = ((LARc[0] & 0x3) << 6) | (LARc[1] & 0x3F); *c++ = ((LARc[2] & 0x1F) << 3) | ((LARc[3] >> 2) & 0x7); *c++ = ((LARc[3] & 0x3) << 6) | ((LARc[4] & 0xF) << 2) | ((LARc[5] >> 2) & 0x3); *c++ = ((LARc[5] & 0x3) << 6) | ((LARc[6] & 0x7) << 3) | (LARc[7] & 0x7); *c++ = ((Nc[0] & 0x7F) << 1) | ((bc[0] >> 1) & 0x1); *c++ = ((bc[0] & 0x1) << 7) | ((Mc[0] & 0x3) << 5) | ((xmaxc[0] >> 1) & 0x1F); *c++ = ((xmaxc[0] & 0x1) << 7) | ((xmc[0] & 0x7) << 4) | ((xmc[1] & 0x7) << 1) | ((xmc[2] >> 2) & 0x1); *c++ = ((xmc[2] & 0x3) << 6) | ((xmc[3] & 0x7) << 3) | (xmc[4] & 0x7); *c++ = ((xmc[5] & 0x7) << 5) /* 10 */ | ((xmc[6] & 0x7) << 2) | ((xmc[7] >> 1) & 0x3); *c++ = ((xmc[7] & 0x1) << 7) | ((xmc[8] & 0x7) << 4) | ((xmc[9] & 0x7) << 1) | ((xmc[10] >> 2) & 0x1); *c++ = ((xmc[10] & 0x3) << 6) | ((xmc[11] & 0x7) << 3) | (xmc[12] & 0x7); *c++ = ((Nc[1] & 0x7F) << 1) | ((bc[1] >> 1) & 0x1); *c++ = ((bc[1] & 0x1) << 7) | ((Mc[1] & 0x3) << 5) | ((xmaxc[1] >> 1) & 0x1F); *c++ = ((xmaxc[1] & 0x1) << 7) | ((xmc[13] & 0x7) << 4) | ((xmc[14] & 0x7) << 1) | ((xmc[15] >> 2) & 0x1); *c++ = ((xmc[15] & 0x3) << 6) | ((xmc[16] & 0x7) << 3) | (xmc[17] & 0x7); *c++ = ((xmc[18] & 0x7) << 5) | ((xmc[19] & 0x7) << 2) | ((xmc[20] >> 1) & 0x3); *c++ = ((xmc[20] & 0x1) << 7) | ((xmc[21] & 0x7) << 4) | ((xmc[22] & 0x7) << 1) | ((xmc[23] >> 2) & 0x1); *c++ = ((xmc[23] & 0x3) << 6) | ((xmc[24] & 0x7) << 3) | (xmc[25] & 0x7); *c++ = ((Nc[2] & 0x7F) << 1) /* 20 */ | ((bc[2] >> 1) & 0x1); *c++ = ((bc[2] & 0x1) << 7) | ((Mc[2] & 0x3) << 5) | ((xmaxc[2] >> 1) & 0x1F); *c++ = ((xmaxc[2] & 0x1) << 7) | ((xmc[26] & 0x7) << 4) | ((xmc[27] & 0x7) << 1) | ((xmc[28] >> 2) & 0x1); *c++ = ((xmc[28] & 0x3) << 6) | ((xmc[29] & 0x7) << 3) | (xmc[30] & 0x7); *c++ = ((xmc[31] & 0x7) << 5) | ((xmc[32] & 0x7) << 2) | ((xmc[33] >> 1) & 0x3); *c++ = ((xmc[33] & 0x1) << 7) | ((xmc[34] & 0x7) << 4) | ((xmc[35] & 0x7) << 1) | ((xmc[36] >> 2) & 0x1); *c++ = ((xmc[36] & 0x3) << 6) | ((xmc[37] & 0x7) << 3) | (xmc[38] & 0x7); *c++ = ((Nc[3] & 0x7F) << 1) | ((bc[3] >> 1) & 0x1); *c++ = ((bc[3] & 0x1) << 7) | ((Mc[3] & 0x3) << 5) | ((xmaxc[3] >> 1) & 0x1F); *c++ = ((xmaxc[3] & 0x1) << 7) | ((xmc[39] & 0x7) << 4) | ((xmc[40] & 0x7) << 1) | ((xmc[41] >> 2) & 0x1); *c++ = ((xmc[41] & 0x3) << 6) /* 30 */ | ((xmc[42] & 0x7) << 3) | (xmc[43] & 0x7); *c++ = ((xmc[44] & 0x7) << 5) | ((xmc[45] & 0x7) << 2) | ((xmc[46] >> 1) & 0x3); *c++ = ((xmc[46] & 0x1) << 7) | ((xmc[47] & 0x7) << 4) | ((xmc[48] & 0x7) << 1) | ((xmc[49] >> 2) & 0x1); *c++ = ((xmc[49] & 0x3) << 6) | ((xmc[50] & 0x7) << 3) | (xmc[51] & 0x7); } } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: cfe9c43d-d97c-4216-b5e5-ccd6a25b582b */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ int gsm_option (gsm r, int opt, int * val) { int result = -1; switch (opt) { case GSM_OPT_LTP_CUT: #ifdef LTP_CUT result = r->ltp_cut; if (val) r->ltp_cut = *val; #endif break; case GSM_OPT_VERBOSE: #ifndef NDEBUG result = r->verbose; if (val) r->verbose = *val; #endif break; case GSM_OPT_FAST: #if defined(FAST) && defined(USE_FLOAT_MUL) result = r->fast; if (val) r->fast = !!*val; #endif break; case GSM_OPT_FRAME_CHAIN: #ifdef WAV49 result = r->frame_chain; if (val) r->frame_chain = *val; #endif break; case GSM_OPT_FRAME_INDEX: #ifdef WAV49 result = r->frame_index; if (val) r->frame_index = *val; #endif break; case GSM_OPT_WAV49: #ifdef WAV49 result = r->wav_fmt; if (val) r->wav_fmt = !!*val; #endif break; default: break; } return result; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 963ff156-506f-4359-9145-371e9060b030 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define SFE_HTK_BAD_FILE_LEN 1666 #define SFE_HTK_NOT_WAVEFORM 1667 /*------------------------------------------------------------------------------ ** Private static functions. */ static int htk_close (SF_PRIVATE *psf) ; static int htk_write_header (SF_PRIVATE *psf, int calc_length) ; static int htk_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int htk_open (SF_PRIVATE *psf) { int subformat ; int error = 0 ; if (psf->is_pipe) return SFE_HTK_NO_PIPE ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = htk_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_HTK) return SFE_BAD_OPEN_FORMAT ; psf->endian = SF_ENDIAN_BIG ; if (htk_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = htk_write_header ; } ; psf->close = htk_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ error = pcm_init (psf) ; break ; default : break ; } ; return error ; } /* htk_open */ /*------------------------------------------------------------------------------ */ static int htk_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) htk_write_header (psf, SF_TRUE) ; return 0 ; } /* htk_close */ static int htk_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int sample_count, sample_period ; current = psf_ftell (psf) ; if (calc_length) psf->filelength = psf_get_filelen (psf) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; if (psf->filelength > 12) sample_count = (psf->filelength - 12) / 2 ; else sample_count = 0 ; sample_period = 10000000 / psf->sf.samplerate ; psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* htk_write_header */ /* ** Found the following info in a comment block within Bill Schottstaedt's ** sndlib library. ** ** HTK format files consist of a contiguous sequence of samples preceded by a ** header. Each sample is a vector of either 2-byte integers or 4-byte floats. ** 2-byte integers are used for compressed forms as described below and for ** vector quantised data as described later in section 5.11. HTK format data ** files can also be used to store speech waveforms as described in section 5.8. ** ** The HTK file format header is 12 bytes long and contains the following data ** nSamples -- number of samples in file (4-byte integer) ** sampPeriod -- sample period in 100ns units (4-byte integer) ** sampSize -- number of bytes per sample (2-byte integer) ** parmKind -- a code indicating the sample kind (2-byte integer) ** ** The parameter kind consists of a 6 bit code representing the basic ** parameter kind plus additional bits for each of the possible qualifiers. ** The basic parameter kind codes are ** ** 0 WAVEFORM sampled waveform ** 1 LPC linear prediction filter coefficients ** 2 LPREFC linear prediction reflection coefficients ** 3 LPCEPSTRA LPC cepstral coefficients ** 4 LPDELCEP LPC cepstra plus delta coefficients ** 5 IREFC LPC reflection coef in 16 bit integer format ** 6 MFCC mel-frequency cepstral coefficients ** 7 FBANK log mel-filter bank channel outputs ** 8 MELSPEC linear mel-filter bank channel outputs ** 9 USER user defined sample kind ** 10 DISCRETE vector quantised data ** ** and the bit-encoding for the qualifiers (in octal) is ** _E 000100 has energy ** _N 000200 absolute energy suppressed ** _D 000400 has delta coefficients ** _A 001000 has acceleration coefficients ** _C 002000 is compressed ** _Z 004000 has zero mean static coef. ** _K 010000 has CRC checksum ** _O 020000 has 0'th cepstral coef. */ static int htk_read_header (SF_PRIVATE *psf) { int sample_count, sample_period, marker ; psf_binheader_readf (psf, "pE444", 0, &sample_count, &sample_period, &marker) ; if (2 * sample_count + 12 != psf->filelength) return SFE_HTK_BAD_FILE_LEN ; if (marker != 0x20000) return SFE_HTK_NOT_WAVEFORM ; psf->sf.channels = 1 ; psf->sf.samplerate = 10000000 / sample_period ; psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n", sample_count, sample_period, psf->sf.samplerate) ; psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; /* HTK always has a 12 byte header. */ psf->dataoffset = 12 ; psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; psf->close = htk_close ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* htk_read_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: c350e972-082e-4c20-8934-03391a723560 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include typedef struct IMA_ADPCM_PRIVATE_tag { int (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; int (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ; int channels, blocksize, samplesperblock, blocks ; int blockcount, samplecount ; int previous [2] ; int stepindx [2] ; unsigned char *block ; short *samples ; #if HAVE_FLEXIBLE_ARRAY unsigned short data [] ; /* ISO C99 struct flexible array. */ #else unsigned short data [1] ; /* This is a hack and might not work. */ #endif } IMA_ADPCM_PRIVATE ; /*============================================================================================ ** Predefined IMA ADPCM data. */ static int ima_indx_adjust [16] = { -1, -1, -1, -1, /* +0 - +3, decrease the step size */ 2, 4, 6, 8, /* +4 - +7, increase the step size */ -1, -1, -1, -1, /* -0 - -3, decrease the step size */ 2, 4, 6, 8, /* -4 - -7, increase the step size */ } ; static int ima_step_size [89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 } ; static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ; static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ; static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ; static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t ima_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t ima_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t ima_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t ima_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int wav_w64_ima_close (SF_PRIVATE *psf) ; static int aiff_ima_close (SF_PRIVATE *psf) ; static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; /*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/ static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ; /*============================================================================================ ** IMA ADPCM Reader initialisation function. */ int wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) { int error ; if (psf->mode == SFM_RDWR) return SFE_BAD_MODE_RW ; if (psf->mode == SFM_READ) if ((error = ima_reader_init (psf, blockalign, samplesperblock))) return error ; if (psf->mode == SFM_WRITE) if ((error = ima_writer_init (psf, blockalign))) return error ; psf->seek = ima_seek ; psf->close = wav_w64_ima_close ; return 0 ; } /* wav_w64_ima_init */ static int wav_w64_ima_close (SF_PRIVATE *psf) { IMA_ADPCM_PRIVATE *pima ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE) { /* If a block has been partially assembled, write it out ** as the final block. */ if (pima->samplecount && pima->samplecount < pima->samplesperblock) pima->encode_block (psf, pima) ; psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; } ; free (psf->fdata) ; psf->fdata = NULL ; return 0 ; } /* wav_w64_ima_close */ int aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) { int error ; if (psf->mode == SFM_RDWR) return SFE_BAD_MODE_RW ; if (psf->mode == SFM_READ) if ((error = ima_reader_init (psf, blockalign, samplesperblock))) return error ; if (psf->mode == SFM_WRITE) if ((error = ima_writer_init (psf, blockalign))) return error ; psf->seek = ima_seek ; psf->close = aiff_ima_close ; return 0 ; } /* aiff_ima_init */ static int aiff_ima_close (SF_PRIVATE *psf) { IMA_ADPCM_PRIVATE *pima ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE) { /* If a block has been partially assembled, write it out ** as the final block. */ if (pima->samplecount && pima->samplecount < pima->samplesperblock) pima->encode_block (psf, pima) ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; } ; free (psf->fdata) ; psf->fdata = NULL ; return 0 ; } /* aiff_ima_close */ /*============================================================================================ ** IMA ADPCM Read Functions. */ static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) { IMA_ADPCM_PRIVATE *pima ; int pimasize, count ; if (psf->mode != SFM_READ) return SFE_BAD_MODE_RW ; pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ; if (! (pima = malloc (pimasize))) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pima ; memset (pima, 0, pimasize) ; pima->samples = (short *)pima->data ; pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ; pima->channels = psf->sf.channels ; pima->blocksize = blockalign ; pima->samplesperblock = samplesperblock ; psf->filelength = psf_get_filelen (psf) ; psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; if (psf->datalength % pima->blocksize) pima->blocks = psf->datalength / pima->blocksize + 1 ; else pima->blocks = psf->datalength / pima->blocksize ; switch (psf->sf.format & SF_FORMAT_TYPEMASK) { case SF_FORMAT_WAV : case SF_FORMAT_W64 : count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ; if (pima->samplesperblock != count) psf_log_printf (psf, "*** Warning : samplesperblock should be %d.\n", count) ; pima->decode_block = wav_w64_ima_decode_block ; psf->sf.frames = pima->samplesperblock * pima->blocks ; break ; case SF_FORMAT_AIFF : psf_log_printf (psf, "still need to check block count\n") ; pima->decode_block = aiff_ima_decode_block ; psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ; break ; default : psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; return SFE_INTERNAL ; break ; } ; pima->decode_block (psf, pima) ; /* Read first block. */ psf->read_short = ima_read_s ; psf->read_int = ima_read_i ; psf->read_float = ima_read_f ; psf->read_double = ima_read_d ; return 0 ; } /* ima_reader_init */ static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) { unsigned char *blockdata ; int chan, k, diff, bytecode ; short step, stepindx, predictor, *sampledata ; static int count = 0 ; count ++ ; pima->blockcount += pima->channels ; pima->samplecount = 0 ; if (pima->blockcount > pima->blocks) { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; return 1 ; } ; if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; /* Read and check the block header. */ for (chan = 0 ; chan < pima->channels ; chan++) { blockdata = pima->block + chan * 34 ; sampledata = pima->samples + chan ; predictor = (blockdata [0] << 8) | (blockdata [1] & 0x80) ; stepindx = blockdata [1] & 0x7F ; { if (count < 5) printf ("\nchan: %d predictor: %d stepindx: %d (%d)\n", chan, predictor, stepindx, ima_step_size [stepindx]) ; } /* FIXME : Do this a better way. */ if (stepindx < 0) stepindx = 0 ; else if (stepindx > 88) stepindx = 88 ; /* ** Pull apart the packed 4 bit samples and store them in their ** correct sample positions. */ for (k = 0 ; k < pima->blocksize - 2 ; k++) { bytecode = blockdata [k + 2] ; sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ; sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ; } ; /* Decode the encoded 4 bit samples. */ for (k = 0 ; k < pima->samplesperblock ; k ++) { step = ima_step_size [stepindx] ; bytecode = pima->samples [pima->channels * k + chan] ; stepindx += ima_indx_adjust [bytecode] ; if (stepindx < 0) stepindx = 0 ; else if (stepindx > 88) stepindx = 88 ; diff = step >> 3 ; if (bytecode & 1) diff += step >> 2 ; if (bytecode & 2) diff += step >> 1 ; if (bytecode & 4) diff += step ; if (bytecode & 8) diff = -diff ; predictor += diff ; pima->samples [pima->channels * k + chan] = predictor ; } ; } ; if (count < 5) { for (k = 0 ; k < 10 ; k++) printf ("% 7d,", pima->samples [k]) ; puts ("") ; } return 1 ; } /* aiff_ima_decode_block */ static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) { int chan, k, step, diff, vpdiff, blockindx, indx ; short bytecode, mask ; static int count = 0 ; if (0 && count == 0) { pima->samples [0] = 0 ; printf ("blocksize : %d\n", pima->blocksize) ; printf ("pima->stepindx [0] : %d\n", pima->stepindx [0]) ; } count ++ ; /* Encode the block header. */ for (chan = 0 ; chan < pima->channels ; chan ++) { blockindx = chan * pima->blocksize ; pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ; pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ; pima->previous [chan] = pima->samples [chan] ; } ; /* Encode second and later samples for every block as a 4 bit value. */ for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) { chan = (pima->channels > 1) ? (k % 2) : 0 ; diff = pima->samples [k] - pima->previous [chan] ; bytecode = 0 ; step = ima_step_size [pima->stepindx [chan]] ; vpdiff = step >> 3 ; if (diff < 0) { bytecode = 8 ; diff = -diff ; } ; mask = 4 ; while (mask) { if (diff >= step) { bytecode |= mask ; diff -= step ; vpdiff += step ; } ; step >>= 1 ; mask >>= 1 ; } ; if (bytecode & 8) pima->previous [chan] -= vpdiff ; else pima->previous [chan] += vpdiff ; if (pima->previous [chan] > 32767) pima->previous [chan] = 32767 ; else if (pima->previous [chan] < -32768) pima->previous [chan] = -32768 ; pima->stepindx [chan] += ima_indx_adjust [bytecode] ; if (pima->stepindx [chan] < 0) pima->stepindx [chan] = 0 ; else if (pima->stepindx [chan] > 88) pima->stepindx [chan] = 88 ; pima->samples [k] = bytecode ; } ; /* Pack the 4 bit encoded samples. */ for (chan = 0 ; chan < pima->channels ; chan ++) { for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels) { blockindx = chan * pima->blocksize + 2 + indx / 2; if (0 && count ++ < 5) printf ("chan: %d blockindx: %3d indx: %3d\n", chan, blockindx, indx) ; pima->block [blockindx] = pima->samples [indx] & 0x0F ; pima->block [blockindx] |= (pima->samples [indx + pima->channels] << 4) & 0xF0 ; } ; } ; /* Write the block to disk. */ if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ; memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ; pima->samplecount = 0 ; pima->blockcount ++ ; return 1 ; } /* aiff_ima_encode_block */ static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) { int chan, k, current, blockindx, indx, indxstart, diff ; short step, bytecode, stepindx [2] ; pima->blockcount ++ ; pima->samplecount = 0 ; if (pima->blockcount > pima->blocks) { memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ; return 1 ; } ; if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ; /* Read and check the block header. */ for (chan = 0 ; chan < pima->channels ; chan++) { current = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ; if (current & 0x8000) current -= 0x10000 ; stepindx [chan] = pima->block [chan*4+2] ; if (stepindx [chan] < 0) stepindx [chan] = 0 ; else if (stepindx [chan] > 88) stepindx [chan] = 88 ; if (pima->block [chan*4+3] != 0) psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ; pima->samples [chan] = current ; } ; /* ** Pull apart the packed 4 bit samples and store them in their ** correct sample positions. */ blockindx = 4 * pima->channels ; indxstart = pima->channels ; while (blockindx < pima->blocksize) { for (chan = 0 ; chan < pima->channels ; chan++) { indx = indxstart + chan ; for (k = 0 ; k < 4 ; k++) { bytecode = pima->block [blockindx++] ; pima->samples [indx] = bytecode & 0x0F ; indx += pima->channels ; pima->samples [indx] = (bytecode >> 4) & 0x0F ; indx += pima->channels ; } ; } ; indxstart += 8 * pima->channels ; } ; /* Decode the encoded 4 bit samples. */ for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) { chan = (pima->channels > 1) ? (k % 2) : 0 ; bytecode = pima->samples [k] & 0xF ; step = ima_step_size [stepindx [chan]] ; current = pima->samples [k - pima->channels] ; diff = step >> 3 ; if (bytecode & 1) diff += step >> 2 ; if (bytecode & 2) diff += step >> 1 ; if (bytecode & 4) diff += step ; if (bytecode & 8) diff = -diff ; current += diff ; if (current > 32767) current = 32767 ; else if (current < -32768) current = -32768 ; stepindx [chan] += ima_indx_adjust [bytecode] ; if (stepindx [chan] < 0) stepindx [chan] = 0 ; else if (stepindx [chan] > 88) stepindx [chan] = 88 ; pima->samples [k] = current ; } ; return 1 ; } /* wav_w64_ima_decode_block */ static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) { int chan, k, step, diff, vpdiff, blockindx, indx, indxstart ; short bytecode, mask ; /* Encode the block header. */ for (chan = 0 ; chan < pima->channels ; chan++) { pima->block [chan*4] = pima->samples [chan] & 0xFF ; pima->block [chan*4+1] = (pima->samples [chan] >> 8) & 0xFF ; pima->block [chan*4+2] = pima->stepindx [chan] ; pima->block [chan*4+3] = 0 ; pima->previous [chan] = pima->samples [chan] ; } ; /* Encode the samples as 4 bit. */ for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++) { chan = (pima->channels > 1) ? (k % 2) : 0 ; diff = pima->samples [k] - pima->previous [chan] ; bytecode = 0 ; step = ima_step_size [pima->stepindx [chan]] ; vpdiff = step >> 3 ; if (diff < 0) { bytecode = 8 ; diff = -diff ; } ; mask = 4 ; while (mask) { if (diff >= step) { bytecode |= mask ; diff -= step ; vpdiff += step ; } ; step >>= 1 ; mask >>= 1 ; } ; if (bytecode & 8) pima->previous [chan] -= vpdiff ; else pima->previous [chan] += vpdiff ; if (pima->previous [chan] > 32767) pima->previous [chan] = 32767 ; else if (pima->previous [chan] < -32768) pima->previous [chan] = -32768 ; pima->stepindx [chan] += ima_indx_adjust [bytecode] ; if (pima->stepindx [chan] < 0) pima->stepindx [chan] = 0 ; else if (pima->stepindx [chan] > 88) pima->stepindx [chan] = 88 ; pima->samples [k] = bytecode ; } ; /* Pack the 4 bit encoded samples. */ blockindx = 4 * pima->channels ; indxstart = pima->channels ; while (blockindx < pima->blocksize) { for (chan = 0 ; chan < pima->channels ; chan++) { indx = indxstart + chan ; for (k = 0 ; k < 4 ; k++) { pima->block [blockindx] = pima->samples [indx] & 0x0F ; indx += pima->channels ; pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ; indx += pima->channels ; blockindx ++ ; } ; } ; indxstart += 8 * pima->channels ; } ; /* Write the block to disk. */ if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ; memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ; pima->samplecount = 0 ; pima->blockcount ++ ; return 1 ; } /* wav_w64_ima_encode_block */ static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock) { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; return total ; } ; if (pima->samplecount >= pima->samplesperblock) pima->decode_block (psf, pima) ; count = (pima->samplesperblock - pima->samplecount) * pima->channels ; count = (len - indx > count) ? count : len - indx ; memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ; indx += count ; pima->samplecount += count / pima->channels ; total = indx ; } ; return total ; } /* ima_read_block */ static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = ima_read_block (psf, pima, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* ima_read_s */ static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = ima_read_block (psf, pima, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = ((int) sptr [k]) << 16 ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* ima_read_i */ static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = ima_read_block (psf, pima, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (float) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* ima_read_f */ static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = ima_read_block (psf, pima, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* ima_read_d */ static sf_count_t ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { IMA_ADPCM_PRIVATE *pima ; int newblock, newsample ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; if (psf->datalength < 0 || psf->dataoffset < 0) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (offset == 0) { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; pima->blockcount = 0 ; pima->decode_block (psf, pima) ; pima->samplecount = 0 ; return 0 ; } ; if (offset < 0 || offset > pima->blocks * pima->samplesperblock) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; newblock = offset / pima->samplesperblock ; newsample = offset % pima->samplesperblock ; if (mode == SFM_READ) { psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ; pima->blockcount = newblock ; pima->decode_block (psf, pima) ; pima->samplecount = newsample ; } else { /* What to do about write??? */ psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; return newblock * pima->samplesperblock + newsample ; } /* ima_seek */ /*========================================================================================== ** IMA ADPCM Write Functions. */ static int ima_writer_init (SF_PRIVATE *psf, int blockalign) { IMA_ADPCM_PRIVATE *pima ; int samplesperblock ; unsigned int pimasize ; if (psf->mode != SFM_WRITE) return SFE_BAD_MODE_RW ; samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ; if ((pima = calloc (1, pimasize)) == NULL) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pima ; pima->channels = psf->sf.channels ; pima->blocksize = blockalign ; pima->samplesperblock = samplesperblock ; pima->block = (unsigned char*) pima->data ; pima->samples = (short*) (pima->data + blockalign) ; pima->samplecount = 0 ; switch (psf->sf.format & SF_FORMAT_TYPEMASK) { case SF_FORMAT_WAV : case SF_FORMAT_W64 : pima->encode_block = wav_w64_ima_encode_block ; break ; case SF_FORMAT_AIFF : pima->encode_block = aiff_ima_encode_block ; break ; default : psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ; return SFE_INTERNAL ; break ; } ; psf->write_short = ima_write_s ; psf->write_int = ima_write_i ; psf->write_float = ima_write_f ; psf->write_double = ima_write_d ; return 0 ; } /* ima_writer_init */ /*========================================================================================== */ static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { count = (pima->samplesperblock - pima->samplecount) * pima->channels ; if (count > len - indx) count = len - indx ; memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ; indx += count ; pima->samplecount += count / pima->channels ; total = indx ; if (pima->samplecount >= pima->samplesperblock) pima->encode_block (psf, pima) ; } ; return total ; } /* ima_write_block */ static sf_count_t ima_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; while (len) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = ima_write_block (psf, pima, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* ima_write_s */ static sf_count_t ima_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = ima_write_block (psf, pima, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* ima_write_i */ static sf_count_t ima_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrintf (normfact * ptr [total + k]) ; count = ima_write_block (psf, pima, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* ima_write_f */ static sf_count_t ima_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { IMA_ADPCM_PRIVATE *pima ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pima = (IMA_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrint (normfact * ptr [total + k]) ; count = ima_write_block (psf, pima, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* ima_write_d */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 75a54b82-ad18-4758-9933-64e00a7f24e0 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #define INTERLEAVE_CHANNELS 6 typedef struct { double buffer [SF_BUFFER_LEN / sizeof (double)] ; sf_count_t channel_len ; sf_count_t (*read_short) (SF_PRIVATE*, short *ptr, sf_count_t len) ; sf_count_t (*read_int) (SF_PRIVATE*, int *ptr, sf_count_t len) ; sf_count_t (*read_float) (SF_PRIVATE*, float *ptr, sf_count_t len) ; sf_count_t (*read_double) (SF_PRIVATE*, double *ptr, sf_count_t len) ; } INTERLEAVE_DATA ; static sf_count_t interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t interleave_seek (SF_PRIVATE*, int mode, sf_count_t samples_from_start) ; int interleave_init (SF_PRIVATE *psf) { INTERLEAVE_DATA *pdata ; if (psf->mode != SFM_READ) return SFE_INTERLEAVE_MODE ; if (psf->interleave) { psf_log_printf (psf, "*** Weird, already have interleave.\n") ; return 666 ; } ; /* Free this in sf_close() function. */ if (! (pdata = malloc (sizeof (INTERLEAVE_DATA)))) return SFE_MALLOC_FAILED ; puts ("interleave_init") ; psf->interleave = pdata ; /* Save the existing methods. */ pdata->read_short = psf->read_short ; pdata->read_int = psf->read_int ; pdata->read_float = psf->read_float ; pdata->read_double = psf->read_double ; pdata->channel_len = psf->sf.frames * psf->bytewidth ; /* Insert our new methods. */ psf->read_short = interleave_read_short ; psf->read_int = interleave_read_int ; psf->read_float = interleave_read_float ; psf->read_double = interleave_read_double ; psf->seek = interleave_seek ; return 0 ; } /* pcm_interleave_init */ /*------------------------------------------------------------------------------ */ static sf_count_t interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) { INTERLEAVE_DATA *pdata ; sf_count_t offset, templen ; int chan, count, k ; short *inptr, *outptr ; if (! (pdata = psf->interleave)) return 0 ; inptr = (short*) pdata->buffer ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { outptr = ptr + chan ; offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; if (psf_fseek (psf, offset, SEEK_SET) != offset) { psf->error = SFE_INTERLEAVE_SEEK ; return 0 ; } ; templen = len / psf->sf.channels ; while (templen > 0) { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short)) count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short) ; else count = (int) templen ; if (pdata->read_short (psf, inptr, count) != count) { psf->error = SFE_INTERLEAVE_READ ; return 0 ; } ; for (k = 0 ; k < count ; k++) { *outptr = inptr [k] ; outptr += psf->sf.channels ; } ; templen -= count ; } ; } ; return len ; } /* interleave_read_short */ static sf_count_t interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) { INTERLEAVE_DATA *pdata ; sf_count_t offset, templen ; int chan, count, k ; int *inptr, *outptr ; if (! (pdata = psf->interleave)) return 0 ; inptr = (int*) pdata->buffer ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { outptr = ptr + chan ; offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; if (psf_fseek (psf, offset, SEEK_SET) != offset) { psf->error = SFE_INTERLEAVE_SEEK ; return 0 ; } ; templen = len / psf->sf.channels ; while (templen > 0) { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int)) count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int) ; else count = (int) templen ; if (pdata->read_int (psf, inptr, count) != count) { psf->error = SFE_INTERLEAVE_READ ; return 0 ; } ; for (k = 0 ; k < count ; k++) { *outptr = inptr [k] ; outptr += psf->sf.channels ; } ; templen -= count ; } ; } ; return len ; } /* interleave_read_int */ static sf_count_t interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) { INTERLEAVE_DATA *pdata ; sf_count_t offset, templen ; int chan, count, k ; float *inptr, *outptr ; if (! (pdata = psf->interleave)) return 0 ; inptr = (float*) pdata->buffer ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { outptr = ptr + chan ; offset = psf->dataoffset + pdata->channel_len * chan + psf->read_current * psf->bytewidth ; /*-printf ("chan : %d read_current : %6lld offset : %6lld\n", chan, psf->read_current, offset) ;-*/ if (psf_fseek (psf, offset, SEEK_SET) != offset) { psf->error = SFE_INTERLEAVE_SEEK ; /*-puts ("interleave_seek error") ; exit (1) ;-*/ return 0 ; } ; templen = len / psf->sf.channels ; while (templen > 0) { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float)) count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float) ; else count = (int) templen ; if (pdata->read_float (psf, inptr, count) != count) { psf->error = SFE_INTERLEAVE_READ ; /*-puts ("interleave_read error") ; exit (1) ;-*/ return 0 ; } ; for (k = 0 ; k < count ; k++) { *outptr = inptr [k] ; outptr += psf->sf.channels ; } ; templen -= count ; } ; } ; return len ; } /* interleave_read_float */ static sf_count_t interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) { INTERLEAVE_DATA *pdata ; sf_count_t offset, templen ; int chan, count, k ; double *inptr, *outptr ; if (! (pdata = psf->interleave)) return 0 ; inptr = (double*) pdata->buffer ; for (chan = 0 ; chan < psf->sf.channels ; chan++) { outptr = ptr + chan ; offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ; if (psf_fseek (psf, offset, SEEK_SET) != offset) { psf->error = SFE_INTERLEAVE_SEEK ; return 0 ; } ; templen = len / psf->sf.channels ; while (templen > 0) { if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double)) count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double) ; else count = (int) templen ; if (pdata->read_double (psf, inptr, count) != count) { psf->error = SFE_INTERLEAVE_READ ; return 0 ; } ; for (k = 0 ; k < count ; k++) { *outptr = inptr [k] ; outptr += psf->sf.channels ; } ; templen -= count ; } ; } ; return len ; } /* interleave_read_double */ /*------------------------------------------------------------------------------ */ static sf_count_t interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) { psf = psf ; mode = mode ; /* ** Do nothing here. This is a place holder to prevent the default ** seek function from being called. */ return samples_from_start ; } /* interleave_seek */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 82314e13-0225-4408-a2f2-e6dab3f38904 */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ /* The IRCAM magic number is weird in that one byte in the number can have ** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask. */ #define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF)) #define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00)) #define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF)) #define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64)) #define IRCAM_02B_MARKER (MAKE_MARKER (0x00, 0x02, 0xA3, 0x64)) #define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00)) #define IRCAM_DATA_OFFSET (1024) /*------------------------------------------------------------------------------ ** Typedefs. */ enum { IRCAM_PCM_16 = 0x00002, IRCAM_FLOAT = 0x00004, IRCAM_ALAW = 0x10001, IRCAM_ULAW = 0x20001, IRCAM_PCM_32 = 0x40004 } ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int ircam_close (SF_PRIVATE *psf) ; static int ircam_write_header (SF_PRIVATE *psf, int calc_length) ; static int ircam_read_header (SF_PRIVATE *psf) ; static int get_encoding (int subformat) ; static const char* get_encoding_str (int encoding) ; /*------------------------------------------------------------------------------ ** Public function. */ int ircam_open (SF_PRIVATE *psf) { int subformat ; int error = SFE_NO_ERROR ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = ircam_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_IRCAM) return SFE_BAD_OPEN_FORMAT ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU) psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; psf->dataoffset = IRCAM_DATA_OFFSET ; if ((error = ircam_write_header (psf, SF_FALSE))) return error ; psf->write_header = ircam_write_header ; } ; psf->close = ircam_close ; switch (subformat) { case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */ error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */ error = alaw_init (psf) ; break ; case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ error = pcm_init (psf) ; break ; case SF_FORMAT_FLOAT : /* 32-bit linear PCM. */ error = float32_init (psf) ; break ; default : break ; } ; return error ; } /* ircam_open */ /*------------------------------------------------------------------------------ */ static int ircam_read_header (SF_PRIVATE *psf) { unsigned int marker, encoding ; float samplerate ; int error = SFE_NO_ERROR ; psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; if (((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER) && ((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER)) { psf_log_printf (psf, "marker: 0x%X\n", marker) ; return SFE_IRCAM_NO_MARKER ; } ; psf->endian = SF_ENDIAN_LITTLE ; if (psf->sf.channels > 256) { psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; /* Sanity checking for endian-ness detection. */ if (psf->sf.channels > 256) { psf_log_printf (psf, "marker: 0x%X\n", marker) ; return SFE_IRCAM_BAD_CHANNELS ; } ; psf->endian = SF_ENDIAN_BIG ; } ; psf_log_printf (psf, "marker: 0x%X\n", marker) ; psf->sf.samplerate = (int) samplerate ; psf_log_printf (psf, " Sample Rate : %d\n" " Channels : %d\n" " Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ; switch (encoding) { case IRCAM_PCM_16 : psf->bytewidth = 2 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ; break ; case IRCAM_PCM_32 : psf->bytewidth = 4 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ; break ; case IRCAM_FLOAT : psf->bytewidth = 4 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ; break ; case IRCAM_ALAW : psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ; break ; case IRCAM_ULAW : psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ; break ; default : error = SFE_IRCAM_UNKNOWN_FORMAT ; break ; } ; if (psf->endian == SF_ENDIAN_BIG) psf->sf.format |= SF_ENDIAN_BIG ; else psf->sf.format |= SF_ENDIAN_LITTLE ; if (error) return error ; psf->dataoffset = IRCAM_DATA_OFFSET ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->sf.frames == 0 && psf->blockwidth) psf->sf.frames = psf->datalength / psf->blockwidth ; psf_log_printf (psf, " Samples : %d\n", psf->sf.frames) ; psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ; return 0 ; } /* ircam_read_header */ static int ircam_close (SF_PRIVATE *psf) { psf_log_printf (psf, "close\n") ; return 0 ; } /* ircam_close */ static int ircam_write_header (SF_PRIVATE *psf, int calc_length) { int encoding ; float samplerate ; sf_count_t current ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; calc_length = calc_length ; /* This also sets psf->endian. */ encoding = get_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ; if (encoding == 0) return SFE_BAD_OPEN_FORMAT ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; samplerate = psf->sf.samplerate ; switch (psf->endian) { case SF_ENDIAN_BIG : psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ; psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ; break ; case SF_ENDIAN_LITTLE : psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ; psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* ircam_write_header */ static int get_encoding (int subformat) { switch (subformat) { case SF_FORMAT_PCM_16 : return IRCAM_PCM_16 ; case SF_FORMAT_PCM_32 : return IRCAM_PCM_32 ; case SF_FORMAT_FLOAT : return IRCAM_FLOAT ; case SF_FORMAT_ULAW : return IRCAM_ULAW ; case SF_FORMAT_ALAW : return IRCAM_ALAW ; default : break ; } ; return 0 ; } /* get_encoding */ static const char* get_encoding_str (int encoding) { switch (encoding) { case IRCAM_PCM_16 : return "16 bit PCM" ; case IRCAM_FLOAT : return "32 bit float" ; case IRCAM_ALAW : return "A law" ; case IRCAM_ULAW : return "u law" ; case IRCAM_PCM_32 : return "32 bit PCM" ; } ; return "Unknown encoding" ; } /* get_encoding_str */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: f2714ab8-f286-4c94-9740-edaf673a1c71 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* * 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION */ /* * This module computes the LTP gain (bc) and the LTP lag (Nc) * for the long term analysis filter. This is done by calculating a * maximum of the cross-correlation function between the current * sub-segment short term residual signal d[0..39] (output of * the short term analysis filter; for simplification the index * of this array begins at 0 and ends at 39 for each sub-segment of the * RPE-LTP analysis) and the previous reconstructed short term * residual signal dp[ -120 .. -1 ]. A dynamic scaling must be * performed to avoid overflow. */ /* The next procedure exists in six versions. First two integer * version (if USE_FLOAT_MUL is not defined); then four floating * point versions, twice with proper scaling (USE_FLOAT_MUL defined), * once without (USE_FLOAT_MUL and FAST defined, and fast run-time * option used). Every pair has first a Cut version (see the -C * option to toast or the LTP_CUT option to gsm_option()), then the * uncut one. (For a detailed explanation of why this is altogether * a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered * Harmful''.) */ #ifndef USE_FLOAT_MUL #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters ( struct gsm_state * st, register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_result; longword L_max, L_power; word R, S, dmax, scal, best_k; word ltp_cut; register word temp, wt_k; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) { dmax = temp; best_k = k; } } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ wt_k = SASR_W(d[best_k], scal); for (lambda = 40; lambda <= 120; lambda++) { L_result = (longword)wt_k * dp[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR_W( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters ( register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word wt[40]; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k <= 39; k++) wt[k] = SASR_W( d[k], scal ); /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { # undef long_termSTEP # define long_termSTEP(k) (longword)wt[k] * dp[k - lambda] register longword L_result; L_result = long_termSTEP(0) ; L_result += long_termSTEP(1) ; L_result += long_termSTEP(2) ; L_result += long_termSTEP(3) ; L_result += long_termSTEP(4) ; L_result += long_termSTEP(5) ; L_result += long_termSTEP(6) ; L_result += long_termSTEP(7) ; L_result += long_termSTEP(8) ; L_result += long_termSTEP(9) ; L_result += long_termSTEP(10) ; L_result += long_termSTEP(11) ; L_result += long_termSTEP(12) ; L_result += long_termSTEP(13) ; L_result += long_termSTEP(14) ; L_result += long_termSTEP(15) ; L_result += long_termSTEP(16) ; L_result += long_termSTEP(17) ; L_result += long_termSTEP(18) ; L_result += long_termSTEP(19) ; L_result += long_termSTEP(20) ; L_result += long_termSTEP(21) ; L_result += long_termSTEP(22) ; L_result += long_termSTEP(23) ; L_result += long_termSTEP(24) ; L_result += long_termSTEP(25) ; L_result += long_termSTEP(26) ; L_result += long_termSTEP(27) ; L_result += long_termSTEP(28) ; L_result += long_termSTEP(29) ; L_result += long_termSTEP(30) ; L_result += long_termSTEP(31) ; L_result += long_termSTEP(32) ; L_result += long_termSTEP(33) ; L_result += long_termSTEP(34) ; L_result += long_termSTEP(35) ; L_result += long_termSTEP(36) ; L_result += long_termSTEP(37) ; L_result += long_termSTEP(38) ; L_result += long_termSTEP(39) ; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR_W( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR_L( L_max << temp, 16 ); S = SASR_L( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #else /* USE_FLOAT_MUL */ #ifdef LTP_CUT static void Cut_Calculation_of_the_LTP_parameters ( struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; word ltp_cut; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = d[k]; temp = GSM_ABS( temp ); if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); ltp_cut = (longword)SASR_W(dmax, scal) * st->ltp_cut / 100; /* Initialization of a working array wt */ for (k = 0; k < 40; k++) { register word w = SASR_W( d[k], scal ); if (w < 0 ? w > -ltp_cut : w < ltp_cut) { wt_float[k] = 0.0; } else { wt_float[k] = w; } } for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef long_termSTEP # define long_termSTEP(K, a, b, c, d, e, f, g, h) \ if ((W = wt_float[K]) != 0.0) { \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E; } else (a = lp[K]) # define long_termSTEP_A(K) long_termSTEP(K, a, b, c, d, e, f, g, h) # define long_termSTEP_B(K) long_termSTEP(K, b, c, d, e, f, g, h, a) # define long_termSTEP_C(K) long_termSTEP(K, c, d, e, f, g, h, a, b) # define long_termSTEP_D(K) long_termSTEP(K, d, e, f, g, h, a, b, c) # define long_termSTEP_E(K) long_termSTEP(K, e, f, g, h, a, b, c, d) # define long_termSTEP_F(K) long_termSTEP(K, f, g, h, a, b, c, d, e) # define long_termSTEP_G(K) long_termSTEP(K, g, h, a, b, c, d, e, f) # define long_termSTEP_H(K) long_termSTEP(K, h, a, b, c, d, e, f, g) long_termSTEP_A( 0); long_termSTEP_B( 1); long_termSTEP_C( 2); long_termSTEP_D( 3); long_termSTEP_E( 4); long_termSTEP_F( 5); long_termSTEP_G( 6); long_termSTEP_H( 7); long_termSTEP_A( 8); long_termSTEP_B( 9); long_termSTEP_C(10); long_termSTEP_D(11); long_termSTEP_E(12); long_termSTEP_F(13); long_termSTEP_G(14); long_termSTEP_H(15); long_termSTEP_A(16); long_termSTEP_B(17); long_termSTEP_C(18); long_termSTEP_D(19); long_termSTEP_E(20); long_termSTEP_F(21); long_termSTEP_G(22); long_termSTEP_H(23); long_termSTEP_A(24); long_termSTEP_B(25); long_termSTEP_C(26); long_termSTEP_D(27); long_termSTEP_E(28); long_termSTEP_F(29); long_termSTEP_G(30); long_termSTEP_H(31); long_termSTEP_A(32); long_termSTEP_B(33); long_termSTEP_C(34); long_termSTEP_D(35); long_termSTEP_E(36); long_termSTEP_F(37); long_termSTEP_G(38); long_termSTEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR_W( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR( L_max << temp, 16 ); S = SASR( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Calculation_of_the_LTP_parameters ( register word * din, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; longword L_max, L_power; word R, S, dmax, scal; register word temp; /* Search of the optimum scaling of d[0..39]. */ dmax = 0; for (k = 0; k <= 39; k++) { temp = din [k] ; temp = GSM_ABS (temp) ; if (temp > dmax) dmax = temp; } temp = 0; if (dmax == 0) scal = 0; else { assert(dmax > 0); temp = gsm_norm( (longword)dmax << 16 ); } if (temp > 6) scal = 0; else scal = 6 - temp; assert(scal >= 0); /* Initialization of a working array wt */ for (k = 0; k < 40; k++) wt_float[k] = SASR_W (din [k], scal) ; for (k = -120; k < 0; k++) dp_float[k] = dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef long_termSTEP # define long_termSTEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define long_termSTEP_A(K) long_termSTEP(K, a, b, c, d, e, f, g, h) # define long_termSTEP_B(K) long_termSTEP(K, b, c, d, e, f, g, h, a) # define long_termSTEP_C(K) long_termSTEP(K, c, d, e, f, g, h, a, b) # define long_termSTEP_D(K) long_termSTEP(K, d, e, f, g, h, a, b, c) # define long_termSTEP_E(K) long_termSTEP(K, e, f, g, h, a, b, c, d) # define long_termSTEP_F(K) long_termSTEP(K, f, g, h, a, b, c, d, e) # define long_termSTEP_G(K) long_termSTEP(K, g, h, a, b, c, d, e, f) # define long_termSTEP_H(K) long_termSTEP(K, h, a, b, c, d, e, f, g) long_termSTEP_A( 0); long_termSTEP_B( 1); long_termSTEP_C( 2); long_termSTEP_D( 3); long_termSTEP_E( 4); long_termSTEP_F( 5); long_termSTEP_G( 6); long_termSTEP_H( 7); long_termSTEP_A( 8); long_termSTEP_B( 9); long_termSTEP_C(10); long_termSTEP_D(11); long_termSTEP_E(12); long_termSTEP_F(13); long_termSTEP_G(14); long_termSTEP_H(15); long_termSTEP_A(16); long_termSTEP_B(17); long_termSTEP_C(18); long_termSTEP_D(19); long_termSTEP_E(20); long_termSTEP_F(21); long_termSTEP_G(22); long_termSTEP_H(23); long_termSTEP_A(24); long_termSTEP_B(25); long_termSTEP_C(26); long_termSTEP_D(27); long_termSTEP_E(28); long_termSTEP_F(29); long_termSTEP_G(30); long_termSTEP_H(31); long_termSTEP_A(32); long_termSTEP_B(33); long_termSTEP_C(34); long_termSTEP_D(35); long_termSTEP_E(36); long_termSTEP_F(37); long_termSTEP_G(38); long_termSTEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; L_max <<= 1; /* Rescaling of L_max */ assert(scal <= 100 && scal >= -100); L_max = L_max >> (6 - scal); /* sub(6, scal) */ assert( Nc <= 120 && Nc >= 40); /* Compute the power of the reconstructed short term residual * signal dp[..] */ L_power = 0; for (k = 0; k <= 39; k++) { register longword L_temp; L_temp = SASR_W( dp[k - Nc], 3 ); L_power += L_temp * L_temp; } L_power <<= 1; /* from L_MULT */ /* Normalization of L_max and L_power */ if (L_max <= 0) { *bc_out = 0; return; } if (L_max >= L_power) { *bc_out = 3; return; } temp = gsm_norm( L_power ); R = SASR_L ( L_max << temp, 16 ); S = SASR_L ( L_power << temp, 16 ); /* Coding of the LTP gain */ /* Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break; *bc_out = bc; } #ifdef FAST #ifdef LTP_CUT static void Cut_Fast_Calculation_of_the_LTP_parameters ( struct gsm_state * st, /* IN */ register word * d, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; register float wt_float; word Nc, bc; word wt_max, best_k, ltp_cut; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_result, L_max, L_power; wt_max = 0; for (k = 0; k < 40; ++k) { if ( d[k] > wt_max) wt_max = d[best_k = k]; else if (-d[k] > wt_max) wt_max = -d[best_k = k]; } assert(wt_max >= 0); wt_float = (float)wt_max; for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k]; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda++) { L_result = wt_float * dp_float[best_k - lambda]; if (L_result > L_max) { Nc = lambda; L_max = L_result; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* LTP_CUT */ static void Fast_Calculation_of_the_LTP_parameters ( register word * din, /* [0..39] IN */ register word * dp, /* [-120..-1] IN */ word * bc_out, /* OUT */ word * Nc_out /* OUT */ ) { register int k, lambda; word Nc, bc; float wt_float[40]; float dp_float_base[120], * dp_float = dp_float_base + 120; register float L_max, L_power; for (k = 0; k < 40; ++k) wt_float[k] = (float) din [k] ; for (k = -120; k < 0; ++k) dp_float[k] = (float) dp [k] ; /* Search for the maximum cross-correlation and coding of the LTP lag */ L_max = 0; Nc = 40; /* index for the maximum cross-correlation */ for (lambda = 40; lambda <= 120; lambda += 9) { /* Calculate L_result for l = lambda .. lambda + 9. */ register float *lp = dp_float - lambda; register float W; register float a = lp[-8], b = lp[-7], c = lp[-6], d = lp[-5], e = lp[-4], f = lp[-3], g = lp[-2], h = lp[-1]; register float E; register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0, S5 = 0, S6 = 0, S7 = 0, S8 = 0; # undef long_termSTEP # define long_termSTEP(K, a, b, c, d, e, f, g, h) \ W = wt_float[K]; \ E = W * a; S8 += E; \ E = W * b; S7 += E; \ E = W * c; S6 += E; \ E = W * d; S5 += E; \ E = W * e; S4 += E; \ E = W * f; S3 += E; \ E = W * g; S2 += E; \ E = W * h; S1 += E; \ a = lp[K]; \ E = W * a; S0 += E # define long_termSTEP_A(K) long_termSTEP(K, a, b, c, d, e, f, g, h) # define long_termSTEP_B(K) long_termSTEP(K, b, c, d, e, f, g, h, a) # define long_termSTEP_C(K) long_termSTEP(K, c, d, e, f, g, h, a, b) # define long_termSTEP_D(K) long_termSTEP(K, d, e, f, g, h, a, b, c) # define long_termSTEP_E(K) long_termSTEP(K, e, f, g, h, a, b, c, d) # define long_termSTEP_F(K) long_termSTEP(K, f, g, h, a, b, c, d, e) # define long_termSTEP_G(K) long_termSTEP(K, g, h, a, b, c, d, e, f) # define long_termSTEP_H(K) long_termSTEP(K, h, a, b, c, d, e, f, g) long_termSTEP_A( 0); long_termSTEP_B( 1); long_termSTEP_C( 2); long_termSTEP_D( 3); long_termSTEP_E( 4); long_termSTEP_F( 5); long_termSTEP_G( 6); long_termSTEP_H( 7); long_termSTEP_A( 8); long_termSTEP_B( 9); long_termSTEP_C(10); long_termSTEP_D(11); long_termSTEP_E(12); long_termSTEP_F(13); long_termSTEP_G(14); long_termSTEP_H(15); long_termSTEP_A(16); long_termSTEP_B(17); long_termSTEP_C(18); long_termSTEP_D(19); long_termSTEP_E(20); long_termSTEP_F(21); long_termSTEP_G(22); long_termSTEP_H(23); long_termSTEP_A(24); long_termSTEP_B(25); long_termSTEP_C(26); long_termSTEP_D(27); long_termSTEP_E(28); long_termSTEP_F(29); long_termSTEP_G(30); long_termSTEP_H(31); long_termSTEP_A(32); long_termSTEP_B(33); long_termSTEP_C(34); long_termSTEP_D(35); long_termSTEP_E(36); long_termSTEP_F(37); long_termSTEP_G(38); long_termSTEP_H(39); if (S0 > L_max) { L_max = S0; Nc = lambda; } if (S1 > L_max) { L_max = S1; Nc = lambda + 1; } if (S2 > L_max) { L_max = S2; Nc = lambda + 2; } if (S3 > L_max) { L_max = S3; Nc = lambda + 3; } if (S4 > L_max) { L_max = S4; Nc = lambda + 4; } if (S5 > L_max) { L_max = S5; Nc = lambda + 5; } if (S6 > L_max) { L_max = S6; Nc = lambda + 6; } if (S7 > L_max) { L_max = S7; Nc = lambda + 7; } if (S8 > L_max) { L_max = S8; Nc = lambda + 8; } } *Nc_out = Nc; if (L_max <= 0.) { *bc_out = 0; return; } /* Compute the power of the reconstructed short term residual * signal dp[..] */ dp_float -= Nc; L_power = 0; for (k = 0; k < 40; ++k) { register float f = dp_float[k]; L_power += f * f; } if (L_max >= L_power) { *bc_out = 3; return; } /* Coding of the LTP gain * Table 4.3a must be used to obtain the level DLB[i] for the * quantization of the LTP gain b to get the coded version bc. */ lambda = L_max / L_power * 32768.; for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break; *bc_out = bc; } #endif /* FAST */ #endif /* USE_FLOAT_MUL */ /* 4.2.12 */ static void Long_term_analysis_filtering ( word bc, /* IN */ word Nc, /* IN */ register word * dp, /* previous d [-120..-1] IN */ register word * d, /* d [0..39] IN */ register word * dpp, /* estimate [0..39] OUT */ register word * e /* long term res. signal [0..39] OUT */ ) /* * In this part, we have to decode the bc parameter to compute * the samples of the estimate dpp[0..39]. The decoding of bc needs the * use of table 4.3b. The long term residual signal e[0..39] * is then calculated to be fed to the RPE encoding section. */ { register int k; # undef long_termSTEP # define long_termSTEP(BP) \ for (k = 0; k <= 39; k++) { \ dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \ e[k] = GSM_SUB( d[k], dpp[k] ); \ } switch (bc) { case 0: long_termSTEP( 3277 ); break; case 1: long_termSTEP( 11469 ); break; case 2: long_termSTEP( 21299 ); break; case 3: long_termSTEP( 32767 ); break; } } void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d' IN */ word * e, /* [0..39] OUT */ word * dpp, /* [0..39] OUT */ word * Nc, /* correlation lag OUT */ word * bc /* gain factor OUT */ ) { assert( d ); assert( dp ); assert( e ); assert( dpp); assert( Nc ); assert( bc ); #if defined(FAST) && defined(USE_FLOAT_MUL) if (S->fast) #if defined (LTP_CUT) if (S->ltp_cut) Cut_Fast_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif /* LTP_CUT */ Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc ); else #endif /* FAST & USE_FLOAT_MUL */ #ifdef LTP_CUT if (S->ltp_cut) Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc); else #endif Calculation_of_the_LTP_parameters(d, dp, bc, Nc); Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e ); } /* 4.3.2 */ void Gsm_Long_Term_Synthesis_Filtering ( struct gsm_state * S, word Ncr, word bcr, register word * erp, /* [0..39] IN */ register word * drp /* [-120..-1] IN, [-120..40] OUT */ ) /* * This procedure uses the bcr and Ncr parameter to realize the * long term synthesis filtering. The decoding of bcr needs * table 4.3b. */ { register int k; word brp, drpp, Nr; /* Check the limits of Nr. */ Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr; S->nrp = Nr; assert(Nr >= 40 && Nr <= 120); /* Decoding of the LTP gain bcr */ brp = gsm_QLB[ bcr ]; /* Computation of the reconstructed short term residual * signal drp[0..39] */ assert(brp != MIN_WORD); for (k = 0; k <= 39; k++) { drpp = GSM_MULT_R( brp, drp[ k - Nr ] ); drp[k] = GSM_ADD( erp[k], drpp ); } /* * Update of the reconstructed short term residual signal * drp[ -1..-120 ] */ for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ]; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: b369b90d-0284-42a0-87b0-99a25bbd93ac */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* * 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION */ /* 4.2.4 */ static void Autocorrelation ( word * s, /* [0..159] IN/OUT */ longword * L_ACF) /* [0..8] OUT */ /* * The goal is to compute the array L_ACF[k]. The signal s[i] must * be scaled in order to avoid an overflow situation. */ { register int k, i; word temp, smax, scalauto; #ifdef USE_FLOAT_MUL float float_s[160]; #endif /* Dynamic scaling of the array s[0..159] */ /* Search for the maximum. */ smax = 0; for (k = 0; k <= 159; k++) { temp = GSM_ABS( s[k] ); if (temp > smax) smax = temp; } /* Computation of the scaling factor. */ if (smax == 0) scalauto = 0; else { assert(smax > 0); scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */ } /* Scaling of the array s[0...159] */ if (scalauto > 0) { # ifdef USE_FLOAT_MUL # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ float_s[k] = (float) \ (s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\ break; # else # define SCALE(n) \ case n: for (k = 0; k <= 159; k++) \ s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\ break; # endif /* USE_FLOAT_MUL */ switch (scalauto) { SCALE(1) SCALE(2) SCALE(3) SCALE(4) } # undef SCALE } # ifdef USE_FLOAT_MUL else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k]; # endif /* Compute the L_ACF[..]. */ { # ifdef USE_FLOAT_MUL register float * sp = float_s; register float sl = *sp; # define lpcSTEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]); # else word * sp = s; word sl = *sp; # define lpcSTEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]); # endif # define NEXTI sl = *++sp for (k = 9; k--; L_ACF[k] = 0) ; lpcSTEP (0); NEXTI; lpcSTEP(0); lpcSTEP(1); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); lpcSTEP(4); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); lpcSTEP(4); lpcSTEP(5); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); lpcSTEP(4); lpcSTEP(5); lpcSTEP(6); NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); lpcSTEP(4); lpcSTEP(5); lpcSTEP(6); lpcSTEP(7); for (i = 8; i <= 159; i++) { NEXTI; lpcSTEP(0); lpcSTEP(1); lpcSTEP(2); lpcSTEP(3); lpcSTEP(4); lpcSTEP(5); lpcSTEP(6); lpcSTEP(7); lpcSTEP(8); } for (k = 9; k--; L_ACF[k] <<= 1) ; } /* Rescaling of the array s[0..159] */ if (scalauto > 0) { assert(scalauto <= 4); for (k = 160; k--; *s++ <<= scalauto) ; } } #if defined(USE_FLOAT_MUL) && defined(FAST) static void Fast_Autocorrelation ( word * s, /* [0..159] IN/OUT */ longword * L_ACF) /* [0..8] OUT */ { register int k, i; float f_L_ACF[9]; float scale; float s_f[160]; register float *sf = s_f; for (i = 0; i < 160; ++i) sf[i] = s[i]; for (k = 0; k <= 8; k++) { register float L_temp2 = 0; register float *sfl = sf - k; for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i]; f_L_ACF[k] = L_temp2; } scale = MAX_LONGWORD / f_L_ACF[0]; for (k = 0; k <= 8; k++) { L_ACF[k] = f_L_ACF[k] * scale; } } #endif /* defined (USE_FLOAT_MUL) && defined (FAST) */ /* 4.2.5 */ static void Reflection_coefficients ( longword * L_ACF, /* 0...8 IN */ register word * r /* 0...7 OUT */ ) { register int i, m, n; register word temp; word ACF[9]; /* 0..8 */ word P[ 9]; /* 0..8 */ word K[ 9]; /* 2..8 */ /* Schur recursion with 16 bits arithmetic. */ if (L_ACF[0] == 0) { for (i = 8; i--; *r++ = 0) ; return; } assert( L_ACF[0] != 0 ); temp = gsm_norm( L_ACF[0] ); assert(temp >= 0 && temp < 32); /* ? overflow ? */ for (i = 0; i <= 8; i++) ACF[i] = SASR_L( L_ACF[i] << temp, 16 ); /* Initialize array P[..] and K[..] for the recursion. */ for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ]; for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ]; /* Compute reflection coefficients */ for (n = 1; n <= 8; n++, r++) { temp = P[1]; temp = GSM_ABS(temp); if (P[0] < temp) { for (i = n; i <= 8; i++) *r++ = 0; return; } *r = gsm_div( temp, P[0] ); assert(*r >= 0); if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */ assert (*r != MIN_WORD); if (n == 8) return; /* Schur recursion */ temp = GSM_MULT_R( P[1], *r ); P[0] = GSM_ADD( P[0], temp ); for (m = 1; m <= 8 - n; m++) { temp = GSM_MULT_R( K[ m ], *r ); P[m] = GSM_ADD( P[ m+1 ], temp ); temp = GSM_MULT_R( P[ m+1 ], *r ); K[m] = GSM_ADD( K[ m ], temp ); } } } /* 4.2.6 */ static void Transformation_to_Log_Area_Ratios ( register word * r /* 0..7 IN/OUT */ ) /* * The following scaling for r[..] and LAR[..] has been used: * * r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1. * LAR[..] = integer( real_LAR[..] * 16384 ); * with -1.625 <= real_LAR <= 1.625 */ { register word temp; register int i; /* Computation of the LAR[0..7] from the r[0..7] */ for (i = 1; i <= 8; i++, r++) { temp = *r; temp = GSM_ABS(temp); assert(temp >= 0); if (temp < 22118) { temp >>= 1; } else if (temp < 31130) { assert( temp >= 11059 ); temp -= 11059; } else { assert( temp >= 26112 ); temp -= 26112; temp <<= 2; } *r = *r < 0 ? -temp : temp; assert( *r != MIN_WORD ); } } /* 4.2.7 */ static void Quantization_and_coding ( register word * LAR /* [0..7] IN/OUT */ ) { register word temp; /* This procedure needs four tables; the following equations * give the optimum scaling for the constants: * * A[0..7] = integer( real_A[0..7] * 1024 ) * B[0..7] = integer( real_B[0..7] * 512 ) * MAC[0..7] = maximum of the LARc[0..7] * MIC[0..7] = minimum of the LARc[0..7] */ # undef lpcSTEP # define lpcSTEP( A, B, MAC, MIC ) \ temp = GSM_MULT( A, *LAR ); \ temp = GSM_ADD( temp, B ); \ temp = GSM_ADD( temp, 256 ); \ temp = SASR_W( temp, 9 ); \ *LAR = temp>MAC ? MAC - MIC : (tempfast) Fast_Autocorrelation (s, L_ACF ); else #endif Autocorrelation (s, L_ACF ); Reflection_coefficients (L_ACF, LARc ); Transformation_to_Log_Area_Ratios (LARc); Quantization_and_coding (LARc); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 63146664-a002-4e1e-8b7b-f0cc8a6a53da */ /* ** Copyright (C) 2003,2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #if (OS_IS_MACOSX == 1) int macbinary3_open (SF_PRIVATE *psf) { if (psf) return 0 ; return 0 ; } /* macbinary3_open */ #else int macbinary3_open (SF_PRIVATE *psf) { psf = psf ; return 0 ; } /* macbinary3_open */ #endif /* OS_IS_MACOSX */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: c397a7d7-1a31-4349-9684-bd29ef06211e */ /* ** Copyright (C) 2003,2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ') int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) { static char rsrc_name [1024] ; struct stat statbuf ; int format ; psf = psf ; snprintf (rsrc_name, sizeof (rsrc_name), "%s/rsrc", filename); /* If there is no resource fork, just return. */ if (stat (rsrc_name, &statbuf) != 0) { psf_log_printf (psf, "No resource fork.\n") ; return 0 ; } ; if (statbuf.st_size == 0) { psf_log_printf (psf, "Have zero size resource fork.\n") ; return 0 ; } ; format = 0 ; return format ; } /* macos_guess_file_type */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 5fbf66d7-9547-442a-9c73-92fd164f3a95 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Information on how to decode and encode this file was obtained in a PDF ** file which I found on http://www.wotsit.org/. ** Also did a lot of testing with GNU Octave but do not have access to ** Matlab (tm) and so could not test it there. */ /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define MAT4_BE_DOUBLE (MAKE_MARKER (0, 0, 0x03, 0xE8)) #define MAT4_LE_DOUBLE (MAKE_MARKER (0, 0, 0, 0)) #define MAT4_BE_FLOAT (MAKE_MARKER (0, 0, 0x03, 0xF2)) #define MAT4_LE_FLOAT (MAKE_MARKER (0x0A, 0, 0, 0)) #define MAT4_BE_PCM_32 (MAKE_MARKER (0, 0, 0x03, 0xFC)) #define MAT4_LE_PCM_32 (MAKE_MARKER (0x14, 0, 0, 0)) #define MAT4_BE_PCM_16 (MAKE_MARKER (0, 0, 0x04, 0x06)) #define MAT4_LE_PCM_16 (MAKE_MARKER (0x1E, 0, 0, 0)) /* Can't see any reason to ever implement this. */ #define MAT4_BE_PCM_U8 (MAKE_MARKER (0, 0, 0x04, 0x1A)) #define MAT4_LE_PCM_U8 (MAKE_MARKER (0x32, 0, 0, 0)) /*------------------------------------------------------------------------------ ** Private static functions. */ static int mat4_close (SF_PRIVATE *psf) ; static int mat4_format_to_encoding (int format, int endian) ; static int mat4_write_header (SF_PRIVATE *psf, int calc_length) ; static int mat4_read_header (SF_PRIVATE *psf) ; static const char * mat4_marker_to_str (int marker) ; /*------------------------------------------------------------------------------ ** Public function. */ int mat4_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = mat4_read_header (psf))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT4) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) psf->endian = SF_ENDIAN_LITTLE ; else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) psf->endian = SF_ENDIAN_BIG ; if ((error = mat4_write_header (psf, SF_FALSE))) return error ; psf->write_header = mat4_write_header ; } ; psf->close = mat4_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; default : break ; } ; if (error) return error ; return error ; } /* mat4_open */ /*------------------------------------------------------------------------------ */ static int mat4_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) mat4_write_header (psf, SF_TRUE) ; return 0 ; } /* mat4_close */ /*------------------------------------------------------------------------------ */ static int mat4_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int encoding ; double samplerate ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; encoding = mat4_format_to_encoding (psf->sf.format & SF_FORMAT_SUBMASK, psf->endian) ; if (encoding == -1) return SFE_BAD_OPEN_FORMAT ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* Need sample rate as a double for writing to the header. */ samplerate = psf->sf.samplerate ; if (psf->endian == SF_ENDIAN_BIG) { psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ; psf_binheader_writef (psf, "E4bd", 11, "samplerate", 11, samplerate) ; psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ; psf_binheader_writef (psf, "E4b", 9, "wavedata", 9) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ; psf_binheader_writef (psf, "e4bd", 11, "samplerate", 11, samplerate) ; psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ; psf_binheader_writef (psf, "e4b", 9, "wavedata", 9) ; } else return SFE_BAD_OPEN_FORMAT ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* mat4_write_header */ static int mat4_read_header (SF_PRIVATE *psf) { int marker, namesize, rows, cols, imag ; double value ; const char *marker_str ; char name [64] ; psf_binheader_readf (psf, "pm", 0, &marker) ; /* MAT4 file must start with a double for the samplerate. */ if (marker == MAT4_BE_DOUBLE) { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; marker_str = "big endian double" ; } else if (marker == MAT4_LE_DOUBLE) { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; marker_str = "little endian double" ; } else return SFE_UNIMPLEMENTED ; psf_log_printf (psf, "GNU Octave 2.0 / MATLAB v4.2 format\nMarker : %s\n", marker_str) ; psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; psf_binheader_readf (psf, "4", &namesize) ; if (namesize >= SIGNED_SIZEOF (name)) return SFE_MAT4_BAD_NAME ; psf_binheader_readf (psf, "b", name, namesize) ; name [namesize] = 0 ; psf_log_printf (psf, " Name : %s\n", name) ; psf_binheader_readf (psf, "d", &value) ; LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), " Value : %f\n", value) ; psf_log_printf (psf, (char*) psf->buffer) ; if ((rows != 1) || (cols != 1)) return SFE_MAT4_NO_SAMPLERATE ; psf->sf.samplerate = (int) value ; /* Now write out the audio data. */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "Marker : %s\n", mat4_marker_to_str (marker)) ; psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; psf_binheader_readf (psf, "4", &namesize) ; if (namesize >= SIGNED_SIZEOF (name)) return SFE_MAT4_BAD_NAME ; psf_binheader_readf (psf, "b", name, namesize) ; name [namesize] = 0 ; psf_log_printf (psf, " Name : %s\n", name) ; psf->dataoffset = psf_ftell (psf) ; if (rows == 0 && cols == 0) { psf_log_printf (psf, "*** Error : zero channel count.\n") ; return SFE_MAT4_ZERO_CHANNELS ; } ; psf->sf.channels = rows ; psf->sf.frames = cols ; psf->sf.format = psf->endian | SF_FORMAT_MAT4 ; switch (marker) { case MAT4_BE_DOUBLE : case MAT4_LE_DOUBLE : psf->sf.format |= SF_FORMAT_DOUBLE ; psf->bytewidth = 8 ; break ; case MAT4_BE_FLOAT : case MAT4_LE_FLOAT : psf->sf.format |= SF_FORMAT_FLOAT ; psf->bytewidth = 4 ; break ; case MAT4_BE_PCM_32 : case MAT4_LE_PCM_32 : psf->sf.format |= SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; break ; case MAT4_BE_PCM_16 : case MAT4_LE_PCM_16 : psf->sf.format |= SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "*** Error : Bad marker %08X\n", marker) ; return SFE_UNIMPLEMENTED ; } ; if ((psf->filelength - psf->dataoffset) < psf->sf.channels * psf->sf.frames * psf->bytewidth) { psf_log_printf (psf, "*** File seems to be truncated. %D <--> %D\n", psf->filelength - psf->dataoffset, psf->sf.channels * psf->sf.frames * psf->bytewidth) ; } else if ((psf->filelength - psf->dataoffset) > psf->sf.channels * psf->sf.frames * psf->bytewidth) psf->dataend = psf->dataoffset + rows * cols * psf->bytewidth ; psf->datalength = psf->filelength - psf->dataoffset - psf->dataend ; psf->sf.sections = 1 ; return 0 ; } /* mat4_read_header */ static int mat4_format_to_encoding (int format, int endian) { switch (format | endian) { case (SF_FORMAT_PCM_16 | SF_ENDIAN_BIG) : return MAT4_BE_PCM_16 ; case (SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE) : return MAT4_LE_PCM_16 ; case (SF_FORMAT_PCM_32 | SF_ENDIAN_BIG) : return MAT4_BE_PCM_32 ; case (SF_FORMAT_PCM_32 | SF_ENDIAN_LITTLE) : return MAT4_LE_PCM_32 ; case (SF_FORMAT_FLOAT | SF_ENDIAN_BIG) : return MAT4_BE_FLOAT ; case (SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE) : return MAT4_LE_FLOAT ; case (SF_FORMAT_DOUBLE | SF_ENDIAN_BIG) : return MAT4_BE_DOUBLE ; case (SF_FORMAT_DOUBLE | SF_ENDIAN_LITTLE) : return MAT4_LE_DOUBLE ; default : break ; } ; return -1 ; } /* mat4_format_to_encoding */ static const char * mat4_marker_to_str (int marker) { static char str [32] ; switch (marker) { case MAT4_BE_PCM_16 : return "big endian 16 bit PCM" ; case MAT4_LE_PCM_16 : return "little endian 16 bit PCM" ; case MAT4_BE_PCM_32 : return "big endian 32 bit PCM" ; case MAT4_LE_PCM_32 : return "little endian 32 bit PCM" ; case MAT4_BE_FLOAT : return "big endian float" ; case MAT4_LE_FLOAT : return "big endian float" ; case MAT4_BE_DOUBLE : return "big endian double" ; case MAT4_LE_DOUBLE : return "little endian double" ; } ; /* This is a little unsafe but is really only for debugging. */ str [sizeof (str) - 1] = 0 ; LSF_SNPRINTF (str, sizeof (str) - 1, "%08X", marker) ; return str ; } /* mat4_marker_to_str */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: f7e5f5d6-fc39-452e-bc4a-59627116ff59 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Information on how to decode and encode this file was obtained in a PDF ** file which I found on http://www.wotsit.org/. ** Also did a lot of testing with GNU Octave but do not have access to ** Matlab (tm) and so could not test it there. */ /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define MATL_MARKER (MAKE_MARKER ('M', 'A', 'T', 'L')) #define IM_MARKER (('I' << 8) + 'M') #define MI_MARKER (('M' << 8) + 'I') /*------------------------------------------------------------------------------ ** Enums and typedefs. */ enum { MAT5_TYPE_SCHAR = 0x1, MAT5_TYPE_UCHAR = 0x2, MAT5_TYPE_INT16 = 0x3, MAT5_TYPE_UINT16 = 0x4, MAT5_TYPE_INT32 = 0x5, MAT5_TYPE_UINT32 = 0x6, MAT5_TYPE_FLOAT = 0x7, MAT5_TYPE_DOUBLE = 0x9, MAT5_TYPE_ARRAY = 0xE, MAT5_TYPE_COMP_USHORT = 0x00020004, MAT5_TYPE_COMP_UINT = 0x00040006 } ; typedef struct { sf_count_t size ; int rows, cols ; char name [32] ; } MAT5_MATRIX ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int mat5_close (SF_PRIVATE *psf) ; static int mat5_write_header (SF_PRIVATE *psf, int calc_length) ; static int mat5_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int mat5_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = mat5_read_header (psf))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT5) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) psf->endian = SF_ENDIAN_LITTLE ; else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0)) psf->endian = SF_ENDIAN_BIG ; if ((error = mat5_write_header (psf, SF_FALSE))) return error ; psf->write_header = mat5_write_header ; } ; psf->close = mat5_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; default : break ; } ; return error ; } /* mat5_open */ /*------------------------------------------------------------------------------ */ static int mat5_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) mat5_write_header (psf, SF_TRUE) ; return 0 ; } /* mat5_close */ /*------------------------------------------------------------------------------ */ static int mat5_write_header (SF_PRIVATE *psf, int calc_length) { static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ; static const char *wd_name = "wavedata\0" ; sf_count_t current, datasize ; int encoding ; current = psf_ftell (psf) ; if (calc_length) { psf_fseek (psf, 0, SEEK_END) ; psf->filelength = psf_ftell (psf) ; psf_fseek (psf, 0, SEEK_SET) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_U8 : encoding = MAT5_TYPE_UCHAR ; break ; case SF_FORMAT_PCM_16 : encoding = MAT5_TYPE_INT16 ; break ; case SF_FORMAT_PCM_32 : encoding = MAT5_TYPE_INT32 ; break ; case SF_FORMAT_FLOAT : encoding = MAT5_TYPE_FLOAT ; break ; case SF_FORMAT_DOUBLE : encoding = MAT5_TYPE_DOUBLE ; break ; default : return SFE_BAD_OPEN_FORMAT ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "S", "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", ") ; psf_get_date_str ((char*) psf->buffer, sizeof (psf->buffer)) ; psf_binheader_writef (psf, "jS", -1, psf->buffer) ; memset (psf->buffer, ' ', 124 - psf->headindex) ; psf_binheader_writef (psf, "b", psf->buffer, 124 - psf->headindex) ; psf->rwf_endian = psf->endian ; if (psf->rwf_endian == SF_ENDIAN_BIG) psf_binheader_writef (psf, "2b", 0x0100, "MI", 2) ; else psf_binheader_writef (psf, "2b", 0x0100, "IM", 2) ; psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ; psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ; psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, 16) ; if (psf->sf.samplerate > 0xFFFF) psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ; else { unsigned short samplerate = psf->sf.samplerate ; psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ; } ; datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ; psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ; psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ; datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ; if (datasize > 0x7FFFFFFF) datasize = 0x7FFFFFFF ; psf_binheader_writef (psf, "t48", encoding, datasize) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* mat5_write_header */ static int mat5_read_header (SF_PRIVATE *psf) { char name [32] ; short version, endian ; int type, size, flags1, flags2, rows, cols ; psf_binheader_readf (psf, "pb", 0, psf->buffer, 124) ; psf->buffer [125] = 0 ; if (strlen ((char*) psf->buffer) >= 124) return SFE_UNIMPLEMENTED ; if (strstr ((char*) psf->buffer, "MATLAB 5.0 MAT-file") == (char*) psf->buffer) psf_log_printf (psf, "%s\n", psf->buffer) ; psf_binheader_readf (psf, "E22", &version, &endian) ; if (endian == MI_MARKER) { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ; } else if (endian == IM_MARKER) { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ; } else return SFE_MAT5_BAD_ENDIAN ; if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) || (CPU_IS_BIG_ENDIAN && endian == MI_MARKER)) version = ENDSWAP_SHORT (version) ; psf_log_printf (psf, "Version : 0x%04X\n", version) ; psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian, (psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ; /*========================================================*/ psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_ARRAY) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_UINT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &flags1, &flags2) ; psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_INT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &rows, &cols) ; psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; if (rows != 1 || cols != 1) return SFE_MAT5_SAMPLE_RATE ; psf_binheader_readf (psf, "4", &type) ; if (type == MAT5_TYPE_SCHAR) { psf_binheader_readf (psf, "4", &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (size > SIGNED_SIZEOF (name) - 1) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; name [size] = 0 ; } else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) { size = type >> 16 ; if (size > 4) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_log_printf (psf, " Type : %X\n", type) ; psf_binheader_readf (psf, "4", &name) ; name [size] = 0 ; } else return SFE_MAT5_NO_BLOCK ; psf_log_printf (psf, " Name : %s\n", name) ; /*-----------------------------------------*/ psf_binheader_readf (psf, "44", &type, &size) ; switch (type) { case MAT5_TYPE_DOUBLE : { double samplerate ; psf_binheader_readf (psf, "d", &samplerate) ; LSF_SNPRINTF (name, sizeof (name), "%f\n", samplerate) ; psf_log_printf (psf, " Val : %s\n", name) ; psf->sf.samplerate = lrint (samplerate) ; } ; break ; case MAT5_TYPE_COMP_USHORT : { unsigned short samplerate ; psf_binheader_readf (psf, "j2j", -4, &samplerate, 2) ; psf_log_printf (psf, " Val : %u\n", samplerate) ; psf->sf.samplerate = samplerate ; } break ; case MAT5_TYPE_COMP_UINT : psf_log_printf (psf, " Val : %u\n", size) ; psf->sf.samplerate = size ; break ; default : psf_log_printf (psf, " Type : %X Size : %d ***\n", type, size) ; return SFE_MAT5_SAMPLE_RATE ; } ; /*-----------------------------------------*/ psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_ARRAY) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_UINT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &flags1, &flags2) ; psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_INT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &rows, &cols) ; psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; psf_binheader_readf (psf, "4", &type) ; if (type == MAT5_TYPE_SCHAR) { psf_binheader_readf (psf, "4", &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (size > SIGNED_SIZEOF (name) - 1) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; name [size] = 0 ; } else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) { size = type >> 16 ; if (size > 4) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_log_printf (psf, " Type : %X\n", type) ; psf_binheader_readf (psf, "4", &name) ; name [size] = 0 ; } else return SFE_MAT5_NO_BLOCK ; psf_log_printf (psf, " Name : %s\n", name) ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; /*++++++++++++++++++++++++++++++++++++++++++++++++++*/ if (rows == 0 && cols == 0) { psf_log_printf (psf, "*** Error : zero channel count.\n") ; return SFE_MAT5_ZERO_CHANNELS ; } ; psf->sf.channels = rows ; psf->sf.frames = cols ; psf->sf.format = psf->endian | SF_FORMAT_MAT5 ; switch (type) { case MAT5_TYPE_DOUBLE : psf_log_printf (psf, "Data type : double\n") ; psf->sf.format |= SF_FORMAT_DOUBLE ; psf->bytewidth = 8 ; break ; case MAT5_TYPE_FLOAT : psf_log_printf (psf, "Data type : float\n") ; psf->sf.format |= SF_FORMAT_FLOAT ; psf->bytewidth = 4 ; break ; case MAT5_TYPE_INT32 : psf_log_printf (psf, "Data type : 32 bit PCM\n") ; psf->sf.format |= SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; break ; case MAT5_TYPE_INT16 : psf_log_printf (psf, "Data type : 16 bit PCM\n") ; psf->sf.format |= SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; case MAT5_TYPE_UCHAR : psf_log_printf (psf, "Data type : unsigned 8 bit PCM\n") ; psf->sf.format |= SF_FORMAT_PCM_U8 ; psf->bytewidth = 1 ; break ; default : psf_log_printf (psf, "*** Error : Bad marker %08X\n", type) ; return SFE_UNIMPLEMENTED ; } ; psf->dataoffset = psf_ftell (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; return 0 ; } /* mat5_read_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: dfdb6742-b2be-4be8-b390-d0c674e8bc8e */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include /* These required here because we write the header in this file. */ #define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F')) #define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E')) #define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' ')) #define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't')) #define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a')) #define WAVE_FORMAT_MS_ADPCM 0x0002 typedef struct { int channels, blocksize, samplesperblock, blocks, dataremaining ; int blockcount ; sf_count_t samplecount ; short *samples ; unsigned char *block ; #if HAVE_FLEXIBLE_ARRAY unsigned short dummydata [] ; /* ISO C99 struct flexible array. */ #else unsigned short dummydata [1] ; /* This is a hack an might not work. */ #endif } MSADPCM_PRIVATE ; /*============================================================================================ ** MS ADPCM static data and functions. */ static int AdaptationTable [] = { 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 } ; /* TODO : The first 7 coef's are are always hardcode and must appear in the actual WAVE file. They should be read in in case a sound program added extras to the list. */ static int AdaptCoeff1 [MSADPCM_ADAPT_COEFF_COUNT] = { 256, 512, 0, 192, 240, 460, 392 } ; static int AdaptCoeff2 [MSADPCM_ADAPT_COEFF_COUNT] = { 0, -256, 0, 64, 0, -208, -232 } ; /*============================================================================================ ** MS ADPCM Block Layout. ** ====================== ** Block is usually 256, 512 or 1024 bytes depending on sample rate. ** For a mono file, the block is laid out as follows: ** byte purpose ** 0 block predictor [0..6] ** 1,2 initial idelta (positive) ** 3,4 sample 1 ** 5,6 sample 0 ** 7..n packed bytecodes ** ** For a stereo file, the block is laid out as follows: ** byte purpose ** 0 block predictor [0..6] for left channel ** 1 block predictor [0..6] for right channel ** 2,3 initial idelta (positive) for left channel ** 4,5 initial idelta (positive) for right channel ** 6,7 sample 1 for left channel ** 8,9 sample 1 for right channel ** 10,11 sample 0 for left channel ** 12,13 sample 0 for right channel ** 14..n packed bytecodes */ /*============================================================================================ ** Static functions. */ static int msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ; static sf_count_t msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) ; static int msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ; static sf_count_t msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) ; static sf_count_t msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t msadpcm_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int msadpcm_close (SF_PRIVATE *psf) ; static void choose_predictor (unsigned int channels, short *data, int *bpred, int *idelta) ; /*============================================================================================ ** MS ADPCM Read Functions. */ int wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) { MSADPCM_PRIVATE *pms ; unsigned int pmssize ; int count ; if (psf->mode == SFM_WRITE) samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; pmssize = sizeof (MSADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ; if (! (psf->fdata = malloc (pmssize))) return SFE_MALLOC_FAILED ; pms = (MSADPCM_PRIVATE*) psf->fdata ; memset (pms, 0, pmssize) ; pms->samples = (short *)pms->dummydata ; pms->block = (unsigned char*) (pms->dummydata + psf->sf.channels * samplesperblock) ; pms->channels = psf->sf.channels ; pms->blocksize = blockalign ; pms->samplesperblock = samplesperblock ; if (psf->mode == SFM_READ) { pms->dataremaining = psf->datalength ; if (psf->datalength % pms->blocksize) pms->blocks = psf->datalength / pms->blocksize + 1 ; else pms->blocks = psf->datalength / pms->blocksize ; count = 2 * (pms->blocksize - 6 * pms->channels) / pms->channels ; if (pms->samplesperblock != count) psf_log_printf (psf, "*** Warning : samplesperblock shoud be %d.\n", count) ; psf->sf.frames = (psf->datalength / pms->blocksize) * pms->samplesperblock ; psf_log_printf (psf, " bpred idelta\n") ; msadpcm_decode_block (psf, pms) ; psf->read_short = msadpcm_read_s ; psf->read_int = msadpcm_read_i ; psf->read_float = msadpcm_read_f ; psf->read_double = msadpcm_read_d ; } ; if (psf->mode == SFM_WRITE) { pms->samples = (short *)pms->dummydata ; pms->samplecount = 0 ; psf->write_short = msadpcm_write_s ; psf->write_int = msadpcm_write_i ; psf->write_float = msadpcm_write_f ; psf->write_double = msadpcm_write_d ; } ; psf->seek = msadpcm_seek ; psf->close = msadpcm_close ; return 0 ; } /* wav_w64_msadpcm_init */ static int msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) { int chan, k, blockindx, sampleindx ; short bytecode, bpred [2], chan_idelta [2] ; int predict ; int current ; int idelta ; pms->blockcount ++ ; pms->samplecount = 0 ; if (pms->blockcount > pms->blocks) { memset (pms->samples, 0, pms->samplesperblock * pms->channels) ; return 1 ; } ; if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ; /* Read and check the block header. */ if (pms->channels == 1) { bpred [0] = pms->block [0] ; if (bpred [0] >= 7) psf_log_printf (psf, "MS ADPCM synchronisation error (%d).\n", bpred [0]) ; chan_idelta [0] = pms->block [1] | (pms->block [2] << 8) ; chan_idelta [1] = 0 ; psf_log_printf (psf, "(%d) (%d)\n", bpred [0], chan_idelta [0]) ; pms->samples [1] = pms->block [3] | (pms->block [4] << 8) ; pms->samples [0] = pms->block [5] | (pms->block [6] << 8) ; blockindx = 7 ; } else { bpred [0] = pms->block [0] ; bpred [1] = pms->block [1] ; if (bpred [0] >= 7 || bpred [1] >= 7) psf_log_printf (psf, "MS ADPCM synchronisation error (%d %d).\n", bpred [0], bpred [1]) ; chan_idelta [0] = pms->block [2] | (pms->block [3] << 8) ; chan_idelta [1] = pms->block [4] | (pms->block [5] << 8) ; psf_log_printf (psf, "(%d, %d) (%d, %d)\n", bpred [0], bpred [1], chan_idelta [0], chan_idelta [1]) ; pms->samples [2] = pms->block [6] | (pms->block [7] << 8) ; pms->samples [3] = pms->block [8] | (pms->block [9] << 8) ; pms->samples [0] = pms->block [10] | (pms->block [11] << 8) ; pms->samples [1] = pms->block [12] | (pms->block [13] << 8) ; blockindx = 14 ; } ; /*-------------------------------------------------------- This was left over from a time when calculations were done as ints rather than shorts. Keep this around as a reminder in case I ever find a file which decodes incorrectly. if (chan_idelta [0] & 0x8000) chan_idelta [0] -= 0x10000 ; if (chan_idelta [1] & 0x8000) chan_idelta [1] -= 0x10000 ; --------------------------------------------------------*/ /* Pull apart the packed 4 bit samples and store them in their ** correct sample positions. */ sampleindx = 2 * pms->channels ; while (blockindx < pms->blocksize) { bytecode = pms->block [blockindx++] ; pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ; pms->samples [sampleindx++] = bytecode & 0x0F ; } ; /* Decode the encoded 4 bit samples. */ for (k = 2 * pms->channels ; k < (pms->samplesperblock * pms->channels) ; k ++) { chan = (pms->channels > 1) ? (k % 2) : 0 ; bytecode = pms->samples [k] & 0xF ; /* Compute next Adaptive Scale Factor (ASF) */ idelta = chan_idelta [chan] ; chan_idelta [chan] = (AdaptationTable [bytecode] * idelta) >> 8 ; /* => / 256 => FIXED_POINT_ADAPTATION_BASE == 256 */ if (chan_idelta [chan] < 16) chan_idelta [chan] = 16 ; if (bytecode & 0x8) bytecode -= 0x10 ; predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]]) + (pms->samples [k - 2 * pms->channels] * AdaptCoeff2 [bpred [chan]])) >> 8 ; /* => / 256 => FIXED_POINT_COEFF_BASE == 256 */ current = (bytecode * idelta) + predict ; if (current > 32767) current = 32767 ; else if (current < -32768) current = -32768 ; pms->samples [k] = current ; } ; return 1 ; } /* msadpcm_decode_block */ static sf_count_t msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { if (pms->blockcount >= pms->blocks && pms->samplecount >= pms->samplesperblock) { memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ; return total ; } ; if (pms->samplecount >= pms->samplesperblock) msadpcm_decode_block (psf, pms) ; count = (pms->samplesperblock - pms->samplecount) * pms->channels ; count = (len - indx > count) ? count : len - indx ; memcpy (&(ptr [indx]), &(pms->samples [pms->samplecount * pms->channels]), count * sizeof (short)) ; indx += count ; pms->samplecount += count / pms->channels ; total = indx ; } ; return total ; } /* msadpcm_read_block */ static sf_count_t msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = msadpcm_read_block (psf, pms, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* msadpcm_read_s */ static sf_count_t msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = msadpcm_read_block (psf, pms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = sptr [k] << 16 ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* msadpcm_read_i */ static sf_count_t msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = msadpcm_read_block (psf, pms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (float) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* msadpcm_read_f */ static sf_count_t msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, readcount = 0, count ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = msadpcm_read_block (psf, pms, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* msadpcm_read_d */ static sf_count_t msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { MSADPCM_PRIVATE *pms ; int newblock, newsample ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; if (psf->datalength < 0 || psf->dataoffset < 0) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (offset == 0) { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; pms->blockcount = 0 ; msadpcm_decode_block (psf, pms) ; pms->samplecount = 0 ; return 0 ; } ; if (offset < 0 || offset > pms->blocks * pms->samplesperblock) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; newblock = offset / pms->samplesperblock ; newsample = offset % pms->samplesperblock ; if (mode == SFM_READ) { psf_fseek (psf, psf->dataoffset + newblock * pms->blocksize, SEEK_SET) ; pms->blockcount = newblock ; msadpcm_decode_block (psf, pms) ; pms->samplecount = newsample ; } else { /* What to do about write??? */ psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; return newblock * pms->samplesperblock + newsample ; } /* msadpcm_seek */ /*========================================================================================== ** MS ADPCM Write Functions. */ void msadpcm_write_adapt_coeffs (SF_PRIVATE *psf) { int k ; for (k = 0 ; k < MSADPCM_ADAPT_COEFF_COUNT ; k++) psf_binheader_writef (psf, "e22", AdaptCoeff1 [k], AdaptCoeff2 [k]) ; } /* msadpcm_write_adapt_coeffs */ /*========================================================================================== */ static int msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) { unsigned int blockindx ; unsigned char byte ; int chan, k, predict, bpred [2], idelta [2], errordelta, newsamp ; choose_predictor (pms->channels, pms->samples, bpred, idelta) ; /* Write the block header. */ if (pms->channels == 1) { pms->block [0] = bpred [0] ; pms->block [1] = idelta [0] & 0xFF ; pms->block [2] = idelta [0] >> 8 ; pms->block [3] = pms->samples [1] & 0xFF ; pms->block [4] = pms->samples [1] >> 8 ; pms->block [5] = pms->samples [0] & 0xFF ; pms->block [6] = pms->samples [0] >> 8 ; blockindx = 7 ; byte = 0 ; /* Encode the samples as 4 bit. */ for (k = 2 ; k < pms->samplesperblock ; k++) { predict = (pms->samples [k-1] * AdaptCoeff1 [bpred [0]] + pms->samples [k-2] * AdaptCoeff2 [bpred [0]]) >> 8 ; errordelta = (pms->samples [k] - predict) / idelta [0] ; if (errordelta < -8) errordelta = -8 ; else if (errordelta > 7) errordelta = 7 ; newsamp = predict + (idelta [0] * errordelta) ; if (newsamp > 32767) newsamp = 32767 ; else if (newsamp < -32768) newsamp = -32768 ; if (errordelta < 0) errordelta += 0x10 ; byte = (byte << 4) | (errordelta & 0xF) ; if (k % 2) { pms->block [blockindx++] = byte ; byte = 0 ; } ; idelta [0] = (idelta [0] * AdaptationTable [errordelta]) >> 8 ; if (idelta [0] < 16) idelta [0] = 16 ; pms->samples [k] = newsamp ; } ; } else { /* Stereo file. */ pms->block [0] = bpred [0] ; pms->block [1] = bpred [1] ; pms->block [2] = idelta [0] & 0xFF ; pms->block [3] = idelta [0] >> 8 ; pms->block [4] = idelta [1] & 0xFF ; pms->block [5] = idelta [1] >> 8 ; pms->block [6] = pms->samples [2] & 0xFF ; pms->block [7] = pms->samples [2] >> 8 ; pms->block [8] = pms->samples [3] & 0xFF ; pms->block [9] = pms->samples [3] >> 8 ; pms->block [10] = pms->samples [0] & 0xFF ; pms->block [11] = pms->samples [0] >> 8 ; pms->block [12] = pms->samples [1] & 0xFF ; pms->block [13] = pms->samples [1] >> 8 ; blockindx = 14 ; byte = 0 ; chan = 1 ; for (k = 4 ; k < 2 * pms->samplesperblock ; k++) { chan = k & 1 ; predict = (pms->samples [k-2] * AdaptCoeff1 [bpred [chan]] + pms->samples [k-4] * AdaptCoeff2 [bpred [chan]]) >> 8 ; errordelta = (pms->samples [k] - predict) / idelta [chan] ; if (errordelta < -8) errordelta = -8 ; else if (errordelta > 7) errordelta = 7 ; newsamp = predict + (idelta [chan] * errordelta) ; if (newsamp > 32767) newsamp = 32767 ; else if (newsamp < -32768) newsamp = -32768 ; if (errordelta < 0) errordelta += 0x10 ; byte = (byte << 4) | (errordelta & 0xF) ; if (chan) { pms->block [blockindx++] = byte ; byte = 0 ; } ; idelta [chan] = (idelta [chan] * AdaptationTable [errordelta]) >> 8 ; if (idelta [chan] < 16) idelta [chan] = 16 ; pms->samples [k] = newsamp ; } ; } ; /* Write the block to disk. */ if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ; memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ; pms->blockcount ++ ; pms->samplecount = 0 ; return 1 ; } /* msadpcm_encode_block */ static sf_count_t msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) { int count, total = 0, indx = 0 ; while (indx < len) { count = (pms->samplesperblock - pms->samplecount) * pms->channels ; if (count > len - indx) count = len - indx ; memcpy (&(pms->samples [pms->samplecount * pms->channels]), &(ptr [total]), count * sizeof (short)) ; indx += count ; pms->samplecount += count / pms->channels ; total = indx ; if (pms->samplecount >= pms->samplesperblock) msadpcm_encode_block (psf, pms) ; } ; return total ; } /* msadpcm_write_block */ static sf_count_t msadpcm_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = msadpcm_write_block (psf, pms, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* msadpcm_write_s */ static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* msadpcm_write_i */ static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrintf (normfact * ptr [total + k]) ; count = msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* msadpcm_write_f */ static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { MSADPCM_PRIVATE *pms ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrint (normfact * ptr [total + k]) ; count = msadpcm_write_block (psf, pms, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* msadpcm_write_d */ /*======================================================================================== */ static int msadpcm_close (SF_PRIVATE *psf) { MSADPCM_PRIVATE *pms ; if (! psf->fdata) return 0 ; pms = (MSADPCM_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE) { /* Now we know static int for certain the length of the file we can ** re-write the header. */ if (pms->samplecount && pms->samplecount < pms->samplesperblock) msadpcm_encode_block (psf, pms) ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; } ; return 0 ; } /* msadpcm_close */ /*======================================================================================== ** Static functions. */ /*---------------------------------------------------------------------------------------- ** Choosing the block predictor. ** Each block requires a predictor and an idelta for each channel. ** The predictor is in the range [0..6] which is an indx into the two AdaptCoeff tables. ** The predictor is chosen by trying all of the possible predictors on a small set of ** samples at the beginning of the block. The predictor with the smallest average ** abs (idelta) is chosen as the best predictor for this block. ** The value of idelta is chosen to to give a 4 bit code value of +/- 4 (approx. half the ** max. code value). If the average abs (idelta) is zero, the sixth predictor is chosen. ** If the value of idelta is less then 16 it is set to 16. ** ** Microsoft uses an IDELTA_COUNT (number of sample pairs used to choose best predictor) ** value of 3. The best possible results would be obtained by using all the samples to ** choose the predictor. */ #define IDELTA_COUNT 3 static void choose_predictor (unsigned int channels, short *data, int *block_pred, int *idelta) { unsigned int chan, k, bpred, idelta_sum, best_bpred, best_idelta ; for (chan = 0 ; chan < channels ; chan++) { best_bpred = best_idelta = 0 ; for (bpred = 0 ; bpred < 7 ; bpred++) { idelta_sum = 0 ; for (k = 2 ; k < 2 + IDELTA_COUNT ; k++) idelta_sum += abs (data [k * channels] - ((data [(k - 1) * channels] * AdaptCoeff1 [bpred] + data [(k - 2) * channels] * AdaptCoeff2 [bpred]) >> 8)) ; idelta_sum /= (4 * IDELTA_COUNT) ; if (bpred == 0 || idelta_sum < best_idelta) { best_bpred = bpred ; best_idelta = idelta_sum ; } ; if (! idelta_sum) { best_bpred = bpred ; best_idelta = 16 ; break ; } ; } ; /* for bpred ... */ if (best_idelta < 16) best_idelta = 16 ; block_pred [chan] = best_bpred ; idelta [chan] = best_idelta ; } ; return ; } /* choose_predictor */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: a98908a3-5305-4935-872b-77d6a86c330f */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** Some of the information used to read NIST files was gleaned from ** reading the code of Bill Schottstaedt's sndlib library ** ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz ** However, no code from that package was used. */ #include #include #include #include /*------------------------------------------------------------------------------ */ #define NIST_HEADER_LENGTH 1024 /*------------------------------------------------------------------------------ ** Private static functions. */ static int nist_close (SF_PRIVATE *psf) ; static int nist_write_header (SF_PRIVATE *psf, int calc_length) ; static int nist_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ */ int nist_open (SF_PRIVATE *psf) { int subformat, error ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = nist_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_NIST) return SFE_BAD_OPEN_FORMAT ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU) psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; if ((error = nist_write_header (psf, SF_FALSE))) return error ; psf->write_header = nist_write_header ; } ; psf->close = nist_close ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; default : error = SFE_UNIMPLEMENTED ; break ; } ; return error ; } /* nist_open */ /*------------------------------------------------------------------------------ */ static char bad_header [] = { 'N', 'I', 'S', 'T', '_', '1', 'A', 0x0d, 0x0a, ' ', ' ', ' ', '1', '0', '2', '4', 0x0d, 0x0a, 0 } ; static int nist_read_header (SF_PRIVATE *psf) { char *psf_header ; int bitwidth = 0, bytes = 0, count, encoding ; char str [64], *cptr ; long samples ; psf->sf.format = SF_FORMAT_NIST ; psf_header = (char*) psf->buffer ; if (sizeof (psf->header) <= NIST_HEADER_LENGTH) return SFE_INTERNAL ; /* Go to start of file and read in the whole header. */ psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ; /* Header is a string, so make sure it is null terminated. */ psf_header [NIST_HEADER_LENGTH] = 0 ; /* Now trim the header after the end marker. */ if ((cptr = strstr (psf_header, "end_head"))) { cptr += strlen ("end_head") + 1 ; cptr [0] = 0 ; } ; if (strstr (psf_header, bad_header) == psf_header) return SFE_NIST_CRLF_CONVERISON ; /* Make sure its a NIST file. */ if (strstr (psf_header, "NIST_1A\n 1024\n") != psf_header) { psf_log_printf (psf, "Not a NIST file.\n") ; return SFE_NIST_BAD_HEADER ; } ; /* Determine sample encoding, start by assuming PCM. */ encoding = SF_FORMAT_PCM_U8 ; if ((cptr = strstr (psf_header, "sample_coding -s"))) { sscanf (cptr, "sample_coding -s%d %63s", &count, str) ; if (strcmp (str, "pcm") == 0) encoding = SF_FORMAT_PCM_U8 ; else if (strcmp (str, "alaw") == 0) encoding = SF_FORMAT_ALAW ; else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0)) encoding = SF_FORMAT_ULAW ; else { psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ; encoding = 0 ; } ; } ; if ((cptr = strstr (psf_header, "channel_count -i "))) sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ; if ((cptr = strstr (psf_header, "sample_rate -i "))) sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ; if ((cptr = strstr (psf_header, "sample_count -i "))) { sscanf (psf_header, "sample_count -i %ld", &samples) ; psf->sf.frames = samples ; } ; if ((cptr = strstr (psf_header, "sample_n_bytes -i "))) sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ; /* Default endian-ness (for 8 bit, u-law, A-law. */ psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; /* This is where we figure out endian-ness. */ if ((cptr = strstr (psf_header, "sample_byte_format -s"))) { sscanf (cptr, "sample_byte_format -s%d %8s", &bytes, str) ; if (bytes > 1) { if (psf->bytewidth == 0) psf->bytewidth = bytes ; else if (psf->bytewidth != bytes) { psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ; return SFE_NIST_BAD_ENCODING ; } ; if (strstr (str, "01") == str) psf->endian = SF_ENDIAN_LITTLE ; else if (strstr (str, "10")) psf->endian = SF_ENDIAN_BIG ; else { psf_log_printf (psf, "Weird endian-ness : %s\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; } ; psf->sf.format |= psf->endian ; } ; if ((cptr = strstr (psf_header, "sample_sig_bits -i "))) sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ; if (strstr (psf_header, "channels_interleaved -s5 FALSE")) { psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; psf->dataoffset = NIST_HEADER_LENGTH ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->datalength = psf->filelength - psf->dataoffset ; psf->close = nist_close ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if (encoding == SF_FORMAT_PCM_U8) { switch (psf->bytewidth) { case 1 : psf->sf.format |= SF_FORMAT_PCM_S8 ; break ; case 2 : psf->sf.format |= SF_FORMAT_PCM_16 ; break ; case 3 : psf->sf.format |= SF_FORMAT_PCM_24 ; break ; case 4 : psf->sf.format |= SF_FORMAT_PCM_32 ; break ; default : break ; } ; } else if (encoding != 0) psf->sf.format |= encoding ; else return SFE_UNIMPLEMENTED ; return 0 ; } /* nist_read_header */ static int nist_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) nist_write_header (psf, SF_TRUE) ; return 0 ; } /* nist_close */ /*========================================================================= */ static int nist_write_header (SF_PRIVATE *psf, int calc_length) { const char *end_str ; long samples ; sf_count_t current ; current = psf_ftell (psf) ; /* Prevent compiler warning. */ calc_length = calc_length ; if (psf->endian == SF_ENDIAN_BIG) end_str = "10" ; else if (psf->endian == SF_ENDIAN_LITTLE) end_str = "01" ; else end_str = "error" ; /* Clear the whole header. */ memset (psf->header, 0, sizeof (psf->header)) ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ; psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ; psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n" "sample_sig_bits -i 8\n") ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ; psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ; psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n" "sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ; break ; case SF_FORMAT_ALAW : psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; case SF_FORMAT_ULAW : psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ; psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ; break ; default : return SFE_UNIMPLEMENTED ; } ; psf->dataoffset = NIST_HEADER_LENGTH ; /* Fix this */ samples = psf->sf.frames ; psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ; psf_asciiheader_printf (psf, "end_head\n") ; /* Zero fill to dataoffset. */ psf_binheader_writef (psf, "z", (size_t) (NIST_HEADER_LENGTH - psf->headindex)) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* nist_write_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: b45ed85d-9e22-4ad9-b78c-4b58b67152a8 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int ogg_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* ogg_open */ #else #define SFE_OGG_NOT_OGG 666 /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define ALAW_MARKER MAKE_MARKER ('A', 'L', 'a', 'w') #define SOUN_MARKER MAKE_MARKER ('S', 'o', 'u', 'n') #define DFIL_MARKER MAKE_MARKER ('d', 'F', 'i', 'l') /*------------------------------------------------------------------------------ ** Private static functions. */ static int ogg_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int ogg_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) return SFE_UNIMPLEMENTED ; if ((error = ogg_read_header (psf))) return error ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_OGG) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; return error ; } /* ogg_open */ /*------------------------------------------------------------------------------ */ static int ogg_read_header (SF_PRIVATE *psf) { int marker ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pm", 0, &marker) ; if (marker != ALAW_MARKER) return SFE_OGG_NOT_OGG ; psf_binheader_readf (psf, "m", &marker) ; if (marker != SOUN_MARKER) return SFE_OGG_NOT_OGG ; psf_binheader_readf (psf, "m", &marker) ; if (marker != DFIL_MARKER) return SFE_OGG_NOT_OGG ; psf_log_printf (psf, "Read only : Psion Palmtop Alaw (.wve)\n" " Sample Rate : 8000\n" " Channels : 1\n" " Encoding : A-law\n") ; psf->dataoffset = 0x20 ; psf->datalength = psf->filelength - psf->dataoffset ; psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_ALAW ; psf->sf.samplerate = 8000 ; psf->sf.frames = psf->datalength ; psf->sf.channels = 1 ; return alaw_init (psf) ; } /* ogg_read_header */ /*------------------------------------------------------------------------------ */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 9ff1fe9c-629e-4e9c-9ef5-3d0eb1e427a0 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define FAP_MARKER (MAKE_MARKER ('f', 'a', 'p', ' ')) #define PAF_MARKER (MAKE_MARKER (' ', 'p', 'a', 'f')) /*------------------------------------------------------------------------------ ** Other defines. */ #define PAF_HEADER_LENGTH 2048 #define PAF24_SAMPLES_PER_BLOCK 10 #define PAF24_BLOCK_SIZE 32 /*------------------------------------------------------------------------------ ** Typedefs. */ typedef struct { int version ; int endianness ; int samplerate ; int format ; int channels ; int source ; } PAF_FMT ; typedef struct { int max_blocks, channels, samplesperblock, blocksize ; int read_block, write_block, read_count, write_count ; sf_count_t sample_count ; int *samples ; unsigned char *block ; #if HAVE_FLEXIBLE_ARRAY int data [] ; /* ISO C99 struct flexible array. */ #else int data [1] ; /* This is a hack and may not work. */ #endif } PAF24_PRIVATE ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int paf24_init (SF_PRIVATE *psf) ; static int paf_read_header (SF_PRIVATE *psf) ; static int paf_write_header (SF_PRIVATE *psf, int calc_length) ; static sf_count_t paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t paf24_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t paf24_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t paf24_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t paf24_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; enum { PAF_PCM_16 = 0, PAF_PCM_24 = 1, PAF_PCM_S8 = 2 } ; /*------------------------------------------------------------------------------ ** Public function. */ int paf_open (SF_PRIVATE *psf) { int subformat, error, endian ; psf->dataoffset = PAF_HEADER_LENGTH ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = paf_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF) return SFE_BAD_OPEN_FORMAT ; endian = psf->sf.format & SF_FORMAT_ENDMASK ; /* PAF is by default big endian. */ psf->endian = SF_ENDIAN_BIG ; if (endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && (endian == SF_ENDIAN_CPU))) psf->endian = SF_ENDIAN_LITTLE ; if ((error = paf_write_header (psf, SF_FALSE))) return error ; psf->write_header = paf_write_header ; } ; switch (subformat) { case SF_FORMAT_PCM_S8 : psf->bytewidth = 1 ; error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : psf->bytewidth = 2 ; error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_24 : /* No bytewidth because of whacky 24 bit encoding. */ error = paf24_init (psf) ; break ; default : return SFE_PAF_UNKNOWN_FORMAT ; } ; return error ; } /* paf_open */ /*------------------------------------------------------------------------------ */ static int paf_read_header (SF_PRIVATE *psf) { PAF_FMT paf_fmt ; int marker ; psf_binheader_readf (psf, "pm", 0, &marker) ; psf_log_printf (psf, "Signature : '%M'\n", marker) ; if (marker == PAF_MARKER) { psf_binheader_readf (psf, "E444444", &(paf_fmt.version), &(paf_fmt.endianness), &(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ; } else if (marker == FAP_MARKER) { psf_binheader_readf (psf, "e444444", &(paf_fmt.version), &(paf_fmt.endianness), &(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ; } else return SFE_PAF_NO_MARKER ; psf_log_printf (psf, "Version : %d\n", paf_fmt.version) ; if (paf_fmt.version != 0) { psf_log_printf (psf, "*** Bad version number. should be zero.\n") ; return SFE_PAF_VERSION ; } ; psf_log_printf (psf, "Sample Rate : %d\n", paf_fmt.samplerate) ; psf_log_printf (psf, "Channels : %d\n", paf_fmt.channels) ; psf_log_printf (psf, "Endianness : %d => ", paf_fmt.endianness) ; if (paf_fmt.endianness) { psf_log_printf (psf, "Little\n", paf_fmt.endianness) ; psf->endian = SF_ENDIAN_LITTLE ; } else { psf_log_printf (psf, "Big\n", paf_fmt.endianness) ; psf->endian = SF_ENDIAN_BIG ; } ; if (psf->filelength < PAF_HEADER_LENGTH) return SFE_PAF_SHORT_HEADER ; psf->datalength = psf->filelength - psf->dataoffset ; psf_binheader_readf (psf, "p", (int) psf->dataoffset) ; psf->sf.samplerate = paf_fmt.samplerate ; psf->sf.channels = paf_fmt.channels ; /* Only fill in type major. */ psf->sf.format = SF_FORMAT_PAF ; psf_log_printf (psf, "Format : %d => ", paf_fmt.format) ; /* PAF is by default big endian. */ psf->sf.format |= paf_fmt.endianness ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; switch (paf_fmt.format) { case PAF_PCM_S8 : psf_log_printf (psf, "8 bit linear PCM\n") ; psf->bytewidth = 1 ; psf->sf.format |= SF_FORMAT_PCM_S8 ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->sf.frames = psf->datalength / psf->blockwidth ; break ; case PAF_PCM_16 : psf_log_printf (psf, "16 bit linear PCM\n") ; psf->bytewidth = 2 ; psf->sf.format |= SF_FORMAT_PCM_16 ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->sf.frames = psf->datalength / psf->blockwidth ; break ; case PAF_PCM_24 : psf_log_printf (psf, "24 bit linear PCM\n") ; psf->bytewidth = 3 ; psf->sf.format |= SF_FORMAT_PCM_24 ; psf->blockwidth = 0 ; psf->sf.frames = PAF24_SAMPLES_PER_BLOCK * psf->datalength / (PAF24_BLOCK_SIZE * psf->sf.channels) ; break ; default : psf_log_printf (psf, "Unknown\n") ; return SFE_PAF_UNKNOWN_FORMAT ; break ; } ; psf_log_printf (psf, "Source : %d => ", paf_fmt.source) ; switch (paf_fmt.source) { case 1 : psf_log_printf (psf, "Analog Recording\n") ; break ; case 2 : psf_log_printf (psf, "Digital Transfer\n") ; break ; case 3 : psf_log_printf (psf, "Multi-track Mixdown\n") ; break ; case 5 : psf_log_printf (psf, "Audio Resulting From DSP Processing\n") ; break ; default : psf_log_printf (psf, "Unknown\n") ; break ; } ; return 0 ; } /* paf_read_header */ static int paf_write_header (SF_PRIVATE *psf, int calc_length) { int paf_format ; /* PAF header already written so no need to re-write. */ if (psf_ftell (psf) >= PAF_HEADER_LENGTH) return 0 ; psf->dataoffset = PAF_HEADER_LENGTH ; psf->dataoffset = PAF_HEADER_LENGTH ; /* Prevent compiler warning. */ calc_length = calc_length ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : paf_format = PAF_PCM_S8 ; break ; case SF_FORMAT_PCM_16 : paf_format = PAF_PCM_16 ; break ; case SF_FORMAT_PCM_24 : paf_format = PAF_PCM_24 ; break ; default : return SFE_PAF_UNKNOWN_FORMAT ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->endian == SF_ENDIAN_BIG) { /* Marker, version, endianness, samplerate */ psf_binheader_writef (psf, "Em444", PAF_MARKER, 0, 0, psf->sf.samplerate) ; /* format, channels, source */ psf_binheader_writef (psf, "E444", paf_format, psf->sf.channels, 0) ; } else if (psf->endian == SF_ENDIAN_LITTLE) { /* Marker, version, endianness, samplerate */ psf_binheader_writef (psf, "em444", FAP_MARKER, 0, 1, psf->sf.samplerate) ; /* format, channels, source */ psf_binheader_writef (psf, "e444", paf_format, psf->sf.channels, 0) ; } ; /* Zero fill to dataoffset. */ psf_binheader_writef (psf, "z", (size_t) (psf->dataoffset - psf->headindex)) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; return psf->error ; } /* paf_write_header */ /*=============================================================================== ** 24 bit PAF files have a really weird encoding. ** For a mono file, 10 samples (each being 3 bytes) are packed into a 32 byte ** block. The 8 ints in this 32 byte block are then endian swapped (as ints) ** if necessary before being written to disk. ** For a stereo file, blocks of 10 samples from the same channel are encoded ** into 32 bytes as for the mono case. The 32 byte blocks are then interleaved ** on disk. ** Reading has to reverse the above process :-). ** Weird!!! ** ** The code below attempts to gain efficiency while maintaining readability. */ static int paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ; static int paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ; static int paf24_close (SF_PRIVATE *psf) ; static int paf24_init (SF_PRIVATE *psf) { PAF24_PRIVATE *ppaf24 ; int paf24size, max_blocks ; paf24size = sizeof (PAF24_PRIVATE) + psf->sf.channels * (PAF24_BLOCK_SIZE + PAF24_SAMPLES_PER_BLOCK * sizeof (int)) ; /* ** Not exatly sure why this needs to be here but the tests ** fail without it. */ psf->last_op = 0 ; if (! (psf->fdata = malloc (paf24size))) return SFE_MALLOC_FAILED ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; memset (ppaf24, 0, paf24size) ; ppaf24->channels = psf->sf.channels ; ppaf24->samples = ppaf24->data ; ppaf24->block = (unsigned char*) (ppaf24->data + PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ; ppaf24->blocksize = PAF24_BLOCK_SIZE * ppaf24->channels ; ppaf24->samplesperblock = PAF24_SAMPLES_PER_BLOCK ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { paf24_read_block (psf, ppaf24) ; /* Read first block. */ psf->read_short = paf24_read_s ; psf->read_int = paf24_read_i ; psf->read_float = paf24_read_f ; psf->read_double = paf24_read_d ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->write_short = paf24_write_s ; psf->write_int = paf24_write_i ; psf->write_float = paf24_write_f ; psf->write_double = paf24_write_d ; } ; psf->seek = paf24_seek ; psf->close = paf24_close ; psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->datalength % PAF24_BLOCK_SIZE) { if (psf->mode == SFM_READ) psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ; max_blocks = psf->datalength / ppaf24->blocksize + 1 ; } else max_blocks = psf->datalength / ppaf24->blocksize ; ppaf24->read_block = 0 ; if (psf->mode == SFM_RDWR) ppaf24->write_block = max_blocks ; else ppaf24->write_block = 0 ; psf->sf.frames = ppaf24->samplesperblock * max_blocks ; ppaf24->sample_count = psf->sf.frames ; return 0 ; } /* paf24_init */ static sf_count_t paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { PAF24_PRIVATE *ppaf24 ; int newblock, newsample ; if (psf->fdata == NULL) { psf->error = SFE_INTERNAL ; return SF_SEEK_ERROR ; } ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; if (mode == SFM_READ && ppaf24->write_count > 0) paf24_write_block (psf, ppaf24) ; newblock = offset / ppaf24->samplesperblock ; newsample = offset % ppaf24->samplesperblock ; switch (mode) { case SFM_READ : if (offset > ppaf24->read_block * ppaf24->samplesperblock + ppaf24->read_count) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; if (psf->last_op == SFM_WRITE && ppaf24->write_count) paf24_write_block (psf, ppaf24) ; psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ; ppaf24->read_block = newblock ; paf24_read_block (psf, ppaf24) ; ppaf24->read_count = newsample ; break ; case SFM_WRITE : if (offset > ppaf24->sample_count) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; if (psf->last_op == SFM_WRITE && ppaf24->write_count) paf24_write_block (psf, ppaf24) ; psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ; ppaf24->write_block = newblock ; paf24_read_block (psf, ppaf24) ; ppaf24->write_count = newsample ; break ; default : psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; return newblock * ppaf24->samplesperblock + newsample ; } /* paf24_seek */ static int paf24_close (SF_PRIVATE *psf) { PAF24_PRIVATE *ppaf24 ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (ppaf24->write_count > 0) paf24_write_block (psf, ppaf24) ; } ; return 0 ; } /* paf24_close */ /*--------------------------------------------------------------------------- */ static int paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) { int k, channel ; unsigned char *cptr ; ppaf24->read_block ++ ; ppaf24->read_count = 0 ; if (ppaf24->read_block * ppaf24->samplesperblock > ppaf24->sample_count) { memset (ppaf24->samples, 0, ppaf24->samplesperblock * ppaf24->channels) ; return 1 ; } ; /* Read the block. */ if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ; if (CPU_IS_LITTLE_ENDIAN) { /* Do endian swapping if necessary. */ if (psf->endian == SF_ENDIAN_BIG) endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; /* Unpack block. */ for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) { channel = k % ppaf24->channels ; cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ; } ; } else { /* Do endian swapping if necessary. */ if (psf->endian == SF_ENDIAN_BIG) endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; /* Unpack block. */ for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) { channel = k % ppaf24->channels ; cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ; } ; } ; return 1 ; } /* paf24_read_block */ static int paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len) { int count, total = 0 ; while (total < len) { if (ppaf24->read_block * ppaf24->samplesperblock >= ppaf24->sample_count) { memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ; return total ; } ; if (ppaf24->read_count >= ppaf24->samplesperblock) paf24_read_block (psf, ppaf24) ; count = (ppaf24->samplesperblock - ppaf24->read_count) * ppaf24->channels ; count = (len - total > count) ? count : len - total ; memcpy (&(ptr [total]), &(ppaf24->samples [ppaf24->read_count * ppaf24->channels]), count * sizeof (int)) ; total += count ; ppaf24->read_count += count / ppaf24->channels ; } ; return total ; } /* paf24_read */ static sf_count_t paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; total += count ; len -= readcount ; } ; return total ; } /* paf24_read_s */ static sf_count_t paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int total ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; total = paf24_read (psf, ppaf24, ptr, len) ; return total ; } /* paf24_read_i */ static sf_count_t paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; float normfact ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* paf24_read_f */ static sf_count_t paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; double normfact ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = paf24_read (psf, ppaf24, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* paf24_read_d */ /*--------------------------------------------------------------------------- */ static int paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) { int k, nextsample, channel ; unsigned char *cptr ; /* First pack block. */ if (CPU_IS_LITTLE_ENDIAN) { for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) { channel = k % ppaf24->channels ; cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; nextsample = ppaf24->samples [k] >> 8 ; cptr [0] = nextsample ; cptr [1] = nextsample >> 8 ; cptr [2] = nextsample >> 16 ; } ; /* Do endian swapping if necessary. */ if (psf->endian == SF_ENDIAN_BIG) endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; } else if (CPU_IS_BIG_ENDIAN) { /* This is correct. */ for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++) { channel = k % ppaf24->channels ; cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ; nextsample = ppaf24->samples [k] >> 8 ; cptr [0] = nextsample ; cptr [1] = nextsample >> 8 ; cptr [2] = nextsample >> 16 ; } ; if (psf->endian == SF_ENDIAN_BIG) endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ; } ; /* Write block to disk. */ if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize) psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ; if (ppaf24->sample_count < ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count) ppaf24->sample_count = ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count ; if (ppaf24->write_count == ppaf24->samplesperblock) { ppaf24->write_block ++ ; ppaf24->write_count = 0 ; } ; return 1 ; } /* paf24_write_block */ static int paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len) { int count, total = 0 ; while (total < len) { count = (ppaf24->samplesperblock - ppaf24->write_count) * ppaf24->channels ; if (count > len - total) count = len - total ; memcpy (&(ppaf24->samples [ppaf24->write_count * ppaf24->channels]), &(ptr [total]), count * sizeof (int)) ; total += count ; ppaf24->write_count += count / ppaf24->channels ; if (ppaf24->write_count >= ppaf24->samplesperblock) paf24_write_block (psf, ppaf24) ; } ; return total ; } /* paf24_write */ static sf_count_t paf24_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = ptr [total + k] << 16 ; count = paf24_write (psf, ppaf24, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* paf24_write_s */ static sf_count_t paf24_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int writecount, count ; sf_count_t total = 0 ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; while (len > 0) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = paf24_write (psf, ppaf24, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* paf24_write_i */ static sf_count_t paf24_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; float normfact ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = lrintf (normfact * ptr [total + k]) ; count = paf24_write (psf, ppaf24, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* paf24_write_f */ static sf_count_t paf24_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { PAF24_PRIVATE *ppaf24 ; int *iptr ; int k, bufferlen, writecount = 0, count ; sf_count_t total = 0 ; double normfact ; if (psf->fdata == NULL) return 0 ; ppaf24 = (PAF24_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = lrint (normfact * ptr [total+k]) ; count = paf24_write (psf, ppaf24, iptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* paf24_write_d */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 477a5308-451e-4bbd-bab4-fab6caa4e884 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Need to be able to handle 3 byte (24 bit) integers. So defined a ** type and use SIZEOF_TRIBYTE instead of (tribyte). */ typedef void tribyte ; #define SIZEOF_TRIBYTE 3 static sf_count_t pcm_read_sc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_uc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_les2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_bet2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_let2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_bei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_lei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_read_sc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_uc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_bes2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_les2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_bet2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_let2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_bei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_lei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_read_sc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_uc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_bes2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_les2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_bet2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_let2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_bei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_lei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_read_sc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_uc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_bes2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_les2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_bet2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_let2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_bei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_read_lei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2sc (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2uc (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2bes (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2les (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2bet (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2let (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2bei (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_s2lei (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2sc (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2uc (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2bes (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2les (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2bet (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2let (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2bei (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_i2lei (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2sc (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2uc (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2bes (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2les (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2bet (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2let (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2bei (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_f2lei (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2sc (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2uc (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2bes (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2les (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2bet (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2let (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2bei (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t pcm_write_d2lei (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void sc2s_array (signed char *src, int count, short *dest) ; static void uc2s_array (unsigned char *src, int count, short *dest) ; static void bet2s_array (tribyte *src, int count, short *dest) ; static void let2s_array (tribyte *src, int count, short *dest) ; static void bei2s_array (int *src, int count, short *dest) ; static void lei2s_array (int *src, int count, short *dest) ; static void sc2i_array (signed char *src, int count, int *dest) ; static void uc2i_array (unsigned char *src, int count, int *dest) ; static void bes2i_array (short *src, int count, int *dest) ; static void les2i_array (short *src, int count, int *dest) ; static void bet2i_array (tribyte *src, int count, int *dest) ; static void let2i_array (tribyte *src, int count, int *dest) ; static void sc2f_array (signed char *src, int count, float *dest, float normfact) ; static void uc2f_array (unsigned char *src, int count, float *dest, float normfact) ; static void bes2f_array (short *src, int count, float *dest, float normfact) ; static void les2f_array (short *src, int count, float *dest, float normfact) ; static void bet2f_array (tribyte *src, int count, float *dest, float normfact) ; static void let2f_array (tribyte *src, int count, float *dest, float normfact) ; static void bei2f_array (int *src, int count, float *dest, float normfact) ; static void lei2f_array (int *src, int count, float *dest, float normfact) ; static void sc2d_array (signed char *src, int count, double *dest, double normfact) ; static void uc2d_array (unsigned char *src, int count, double *dest, double normfact) ; static void bes2d_array (short *src, int count, double *dest, double normfact) ; static void les2d_array (short *src, int count, double *dest, double normfact) ; static void bet2d_array (tribyte *src, int count, double *dest, double normfact) ; static void let2d_array (tribyte *src, int count, double *dest, double normfact) ; static void bei2d_array (int *src, int count, double *dest, double normfact) ; static void lei2d_array (int *src, int count, double *dest, double normfact) ; static void s2sc_array (short *src, signed char *dest, int count) ; static void s2uc_array (short *src, unsigned char *dest, int count) ; static void s2bet_array (short *src, tribyte *dest, int count) ; static void s2let_array (short *src, tribyte *dest, int count) ; static void s2bei_array (short *src, int *dest, int count) ; static void s2lei_array (short *src, int *dest, int count) ; static void i2sc_array (int *src, signed char *dest, int count) ; static void i2uc_array (int *src, unsigned char *dest, int count) ; static void i2bes_array (int *src, short *dest, int count) ; static void i2les_array (int *src, short *dest, int count) ; static void i2bet_array (int *src, tribyte *dest, int count) ; static void i2let_array (int *src, tribyte *dest, int count) ; /*----------------------------------------------------------------------------------------------- */ enum { /* Char type for 8 bit files. */ SF_CHARS_SIGNED = 200, SF_CHARS_UNSIGNED = 201 } ; /*----------------------------------------------------------------------------------------------- */ int pcm_init (SF_PRIVATE *psf) { int chars = 0 ; if (psf->bytewidth == 0 || psf->sf.channels == 0) return SFE_INTERNAL ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_S8) chars = SF_CHARS_SIGNED ; else if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_PCM_U8) chars = SF_CHARS_UNSIGNED ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { switch (psf->bytewidth * 0x10000 + psf->endian + chars) { case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_SIGNED) : case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_SIGNED) : psf->read_short = pcm_read_sc2s ; psf->read_int = pcm_read_sc2i ; psf->read_float = pcm_read_sc2f ; psf->read_double = pcm_read_sc2d ; break ; case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_UNSIGNED) : case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_UNSIGNED) : psf->read_short = pcm_read_uc2s ; psf->read_int = pcm_read_uc2i ; psf->read_float = pcm_read_uc2f ; psf->read_double = pcm_read_uc2d ; break ; case (2 * 0x10000 + SF_ENDIAN_BIG) : psf->read_short = pcm_read_bes2s ; psf->read_int = pcm_read_bes2i ; psf->read_float = pcm_read_bes2f ; psf->read_double = pcm_read_bes2d ; break ; case (3 * 0x10000 + SF_ENDIAN_BIG) : psf->read_short = pcm_read_bet2s ; psf->read_int = pcm_read_bet2i ; psf->read_float = pcm_read_bet2f ; psf->read_double = pcm_read_bet2d ; break ; case (4 * 0x10000 + SF_ENDIAN_BIG) : psf->read_short = pcm_read_bei2s ; psf->read_int = pcm_read_bei2i ; psf->read_float = pcm_read_bei2f ; psf->read_double = pcm_read_bei2d ; break ; case (2 * 0x10000 + SF_ENDIAN_LITTLE) : psf->read_short = pcm_read_les2s ; psf->read_int = pcm_read_les2i ; psf->read_float = pcm_read_les2f ; psf->read_double = pcm_read_les2d ; break ; case (3 * 0x10000 + SF_ENDIAN_LITTLE) : psf->read_short = pcm_read_let2s ; psf->read_int = pcm_read_let2i ; psf->read_float = pcm_read_let2f ; psf->read_double = pcm_read_let2d ; break ; case (4 * 0x10000 + SF_ENDIAN_LITTLE) : psf->read_short = pcm_read_lei2s ; psf->read_int = pcm_read_lei2i ; psf->read_float = pcm_read_lei2f ; psf->read_double = pcm_read_lei2d ; break ; default : psf_log_printf (psf, "pcm.c returning SFE_UNIMPLEMENTED\n") ; return SFE_UNIMPLEMENTED ; } ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { switch (psf->bytewidth * 0x10000 + psf->endian + chars) { case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_SIGNED) : case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_SIGNED) : psf->write_short = pcm_write_s2sc ; psf->write_int = pcm_write_i2sc ; psf->write_float = pcm_write_f2sc ; psf->write_double = pcm_write_d2sc ; break ; case (0x10000 + SF_ENDIAN_BIG + SF_CHARS_UNSIGNED) : case (0x10000 + SF_ENDIAN_LITTLE + SF_CHARS_UNSIGNED) : psf->write_short = pcm_write_s2uc ; psf->write_int = pcm_write_i2uc ; psf->write_float = pcm_write_f2uc ; psf->write_double = pcm_write_d2uc ; break ; case (2 * 0x10000 + SF_ENDIAN_BIG) : psf->write_short = pcm_write_s2bes ; psf->write_int = pcm_write_i2bes ; psf->write_float = pcm_write_f2bes ; psf->write_double = pcm_write_d2bes ; break ; case (3 * 0x10000 + SF_ENDIAN_BIG) : psf->write_short = pcm_write_s2bet ; psf->write_int = pcm_write_i2bet ; psf->write_float = pcm_write_f2bet ; psf->write_double = pcm_write_d2bet ; break ; case (4 * 0x10000 + SF_ENDIAN_BIG) : psf->write_short = pcm_write_s2bei ; psf->write_int = pcm_write_i2bei ; psf->write_float = pcm_write_f2bei ; psf->write_double = pcm_write_d2bei ; break ; case (2 * 0x10000 + SF_ENDIAN_LITTLE) : psf->write_short = pcm_write_s2les ; psf->write_int = pcm_write_i2les ; psf->write_float = pcm_write_f2les ; psf->write_double = pcm_write_d2les ; break ; case (3 * 0x10000 + SF_ENDIAN_LITTLE) : psf->write_short = pcm_write_s2let ; psf->write_int = pcm_write_i2let ; psf->write_float = pcm_write_f2let ; psf->write_double = pcm_write_d2let ; break ; case (4 * 0x10000 + SF_ENDIAN_LITTLE) : psf->write_short = pcm_write_s2lei ; psf->write_int = pcm_write_i2lei ; psf->write_float = pcm_write_f2lei ; psf->write_double = pcm_write_d2lei ; break ; default : psf_log_printf (psf, "pcm.c returning SFE_UNIMPLEMENTED\n") ; return SFE_UNIMPLEMENTED ; } ; } ; if (psf->filelength > psf->dataoffset) { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; } else psf->datalength = 0 ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* pcm_init */ /*----------------------------------------------------------------------------------------------- */ static sf_count_t pcm_read_sc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; sc2s_array ((signed char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_sc2s */ static sf_count_t pcm_read_uc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (unsigned char), readcount, psf) ; uc2s_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_uc2s */ static sf_count_t pcm_read_bes2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (short), len, psf) ; if (CPU_IS_LITTLE_ENDIAN) endswap_short_array (ptr, len) ; return total ; } /* pcm_read_bes2s */ static sf_count_t pcm_read_les2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (short), len, psf) ; if (CPU_IS_BIG_ENDIAN) endswap_short_array (ptr, len) ; return total ; } /* pcm_read_les2s */ static sf_count_t pcm_read_bet2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; bet2s_array ((tribyte*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bet2s */ static sf_count_t pcm_read_let2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; let2s_array ((tribyte*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_let2s */ static sf_count_t pcm_read_bei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; bei2s_array ((int*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bei2s */ static sf_count_t pcm_read_lei2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; lei2s_array ((int*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_lei2s */ /*----------------------------------------------------------------------------------------------- */ static sf_count_t pcm_read_sc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; sc2i_array ((signed char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_sc2i */ static sf_count_t pcm_read_uc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (unsigned char), readcount, psf) ; uc2i_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_uc2i */ static sf_count_t pcm_read_bes2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; bes2i_array ((short*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bes2i */ static sf_count_t pcm_read_les2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; les2i_array ((short*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_les2i */ static sf_count_t pcm_read_bet2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; bet2i_array ((tribyte*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bet2i */ static sf_count_t pcm_read_let2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; let2i_array ((tribyte*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_let2i */ static sf_count_t pcm_read_bei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (int), len, psf) ; if (CPU_IS_LITTLE_ENDIAN) endswap_int_array (ptr, len) ; return total ; } /* pcm_read_bei2i */ static sf_count_t pcm_read_lei2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int total ; total = psf_fread (ptr, sizeof (int), len, psf) ; if (CPU_IS_BIG_ENDIAN) endswap_int_array (ptr, len) ; return total ; } /* pcm_read_lei2i */ /*----------------------------------------------------------------------------------------------- */ static sf_count_t pcm_read_sc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; sc2f_array ((signed char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_sc2f */ static sf_count_t pcm_read_uc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (unsigned char), readcount, psf) ; uc2f_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_uc2f */ static sf_count_t pcm_read_bes2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; bes2f_array ((short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bes2f */ static sf_count_t pcm_read_les2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; les2f_array ((short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_les2f */ static sf_count_t pcm_read_bet2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; /* Special normfactor because tribyte value is read into an int. */ normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 / 256.0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; bet2f_array ((tribyte*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bet2f */ static sf_count_t pcm_read_let2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; /* Special normfactor because tribyte value is read into an int. */ normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 / 256.0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; let2f_array ((tribyte*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_let2f */ static sf_count_t pcm_read_bei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; bei2f_array ((int*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bei2f */ static sf_count_t pcm_read_lei2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; lei2f_array ((int*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_lei2f */ /*----------------------------------------------------------------------------------------------- */ static sf_count_t pcm_read_sc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; sc2d_array ((signed char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_sc2d */ static sf_count_t pcm_read_uc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (unsigned char), readcount, psf) ; uc2d_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_uc2d */ static sf_count_t pcm_read_bes2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; bes2d_array ((short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bes2d */ static sf_count_t pcm_read_les2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; les2d_array ((short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_les2d */ static sf_count_t pcm_read_bet2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 / 256.0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; bet2d_array ((tribyte*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bet2d */ static sf_count_t pcm_read_let2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; /* Special normfactor because tribyte value is read into an int. */ normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 / 256.0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, SIZEOF_TRIBYTE, readcount, psf) ; let2d_array ((tribyte*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_let2d */ static sf_count_t pcm_read_bei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; bei2d_array ((int*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_bei2d */ static sf_count_t pcm_read_lei2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (int), readcount, psf) ; lei2d_array ((int*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* pcm_read_lei2d */ /*=============================================================================================== **----------------------------------------------------------------------------------------------- **=============================================================================================== */ static sf_count_t pcm_write_s2sc (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2sc_array (ptr + total, (signed char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2sc */ static sf_count_t pcm_write_s2uc (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2uc_array (ptr + total, (unsigned char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (unsigned char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2uc */ static sf_count_t pcm_write_s2bes (SF_PRIVATE *psf, short *ptr, sf_count_t len) { if (CPU_IS_BIG_ENDIAN) return psf_fwrite (ptr, sizeof (short), len, psf) ; else { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_short_copy ((short*) (psf->buffer), ptr + total, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } ; } /* pcm_write_s2bes */ static sf_count_t pcm_write_s2les (SF_PRIVATE *psf, short *ptr, sf_count_t len) { if (CPU_IS_LITTLE_ENDIAN) return psf_fwrite (ptr, sizeof (short), len, psf) ; else { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_short_copy ((short*) (psf->buffer), ptr + total, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } ; } /* pcm_write_s2les */ static sf_count_t pcm_write_s2bet (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2bet_array (ptr + total, (tribyte*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2bet */ static sf_count_t pcm_write_s2let (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2let_array (ptr + total, (tribyte*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2let */ static sf_count_t pcm_write_s2bei (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2bei_array (ptr + total, (int*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2bei */ static sf_count_t pcm_write_s2lei (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2lei_array (ptr + total, (int*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_s2lei */ /*----------------------------------------------------------------------------------------------- */ static sf_count_t pcm_write_i2sc (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2sc_array (ptr + total, (signed char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2sc */ static sf_count_t pcm_write_i2uc (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2uc_array (ptr + total, (unsigned char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2uc */ static sf_count_t pcm_write_i2bes (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2bes_array (ptr + total, (short*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2bes */ static sf_count_t pcm_write_i2les (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2les_array (ptr + total, (short*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2les */ static sf_count_t pcm_write_i2bet (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2bet_array (ptr + total, (tribyte*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2bet */ static sf_count_t pcm_write_i2let (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2let_array (ptr + total, (tribyte*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_i2les */ static sf_count_t pcm_write_i2bei (SF_PRIVATE *psf, int *ptr, sf_count_t len) { if (CPU_IS_BIG_ENDIAN) return psf_fwrite (ptr, sizeof (int), len, psf) ; else { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_int_copy ((int*) (psf->buffer), ptr + total, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } ; } /* pcm_write_i2bei */ static sf_count_t pcm_write_i2lei (SF_PRIVATE *psf, int *ptr, sf_count_t len) { if (CPU_IS_LITTLE_ENDIAN) return psf_fwrite (ptr, sizeof (int), len, psf) ; else { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; endswap_int_copy ((int*) (psf->buffer), ptr + total, writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } ; } /* pcm_write_i2lei */ /*------------------------------------------------------------------------------ **============================================================================== **------------------------------------------------------------------------------ */ static void f2sc_array (float *src, signed char *dest, int count, int normalize) { float normfact ; normfact = normalize ? (1.0 * 0x7F) : 1.0 ; while (count) { count -- ; dest [count] = lrintf (src [count] * normfact) ; } ; } /* f2sc_array */ static void f2sc_clip_array (float *src, signed char *dest, int count, int normalize) { float normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; while (count) { count -- ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { dest [count] = 127 ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { dest [count] = -128 ; continue ; } ; dest [count] = lrintf (scaled_value) >> 24 ; } ; } /* f2sc_clip_array */ static sf_count_t pcm_write_f2sc (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, signed char *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2sc_clip_array : f2sc_array ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (signed char*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2sc */ /*============================================================================== */ static void f2uc_array (float *src, unsigned char *dest, int count, int normalize) { float normfact ; normfact = normalize ? (1.0 * 0x7F) : 1.0 ; while (count) { count -- ; dest [count] = lrintf (src [count] * normfact) + 128 ; } ; } /* f2uc_array */ static void f2uc_clip_array (float *src, unsigned char *dest, int count, int normalize) { float normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; while (count) { count -- ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { dest [count] = 0xFF ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { dest [count] = 0 ; continue ; } ; dest [count] = (lrintf (scaled_value) >> 24) + 128 ; } ; } /* f2uc_clip_array */ static sf_count_t pcm_write_f2uc (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, unsigned char *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2uc_clip_array : f2uc_array ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (unsigned char*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (unsigned char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2uc */ /*============================================================================== */ static void f2bes_array (float *src, short *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; short value ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; value = lrintf (src [count] * normfact) ; ucptr [1] = value ; ucptr [0] = value >> 8 ; } ; } /* f2bes_array */ static void f2bes_clip_array (float *src, short *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; } ; value = lrintf (scaled_value) ; ucptr [1] = value >> 16 ; ucptr [0] = value >> 24 ; } ; } /* f2bes_clip_array */ static sf_count_t pcm_write_f2bes (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, short *t, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2bes_clip_array : f2bes_array ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (short*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2bes */ /*============================================================================== */ static void f2les_array (float *src, short *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; int value ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; value = lrintf (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; } ; } /* f2les_array */ static void f2les_clip_array (float *src, short *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x80 ; continue ; } ; value = lrintf (scaled_value) ; ucptr [0] = value >> 16 ; ucptr [1] = value >> 24 ; } ; } /* f2les_clip_array */ static sf_count_t pcm_write_f2les (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, short *t, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2les_clip_array : f2les_array ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (short*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2les */ /*============================================================================== */ static void f2let_array (float *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; int value ; normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = lrintf (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; } ; } /* f2let_array */ static void f2let_clip_array (float *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0xFF ; ucptr [2] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x80 ; continue ; } ; value = lrintf (scaled_value) ; ucptr [0] = value >> 8 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 24 ; } ; } /* f2let_clip_array */ static sf_count_t pcm_write_f2let (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, tribyte *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2let_clip_array : f2let_array ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (tribyte*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2let */ /*============================================================================== */ static void f2bet_array (float *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; int value ; normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = lrintf (src [count] * normfact) ; ucptr [0] = value >> 16 ; ucptr [1] = value >> 8 ; ucptr [2] = value ; } ; } /* f2bet_array */ static void f2bet_clip_array (float *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0x7F ; ucptr [1] = 0xFF ; ucptr [2] = 0xFF ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x80 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; continue ; } ; value = lrint (scaled_value) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; } ; } /* f2bet_clip_array */ static sf_count_t pcm_write_f2bet (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, tribyte *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2bet_clip_array : f2bet_array ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (tribyte*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2bet */ /*============================================================================== */ static void f2bei_array (float *src, int *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; int value ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; value = lrintf (src [count] * normfact) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; ucptr [3] = value ; } ; } /* f2bei_array */ static void f2bei_clip_array (float *src, int *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= 1.0 * 0x7FFFFFFF) { ucptr [0] = 0x7F ; ucptr [1] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0xFF ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x80 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x00 ; continue ; } ; value = lrintf (scaled_value) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; ucptr [3] = value ; } ; } /* f2bei_clip_array */ static sf_count_t pcm_write_f2bei (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, int *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2bei_clip_array : f2bei_array ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (int*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2bei */ /*============================================================================== */ static void f2lei_array (float *src, int *dest, int count, int normalize) { unsigned char *ucptr ; float normfact ; int value ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; value = lrintf (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; ucptr [3] = value >> 24 ; } ; } /* f2lei_array */ static void f2lei_clip_array (float *src, int *dest, int count, int normalize) { unsigned char *ucptr ; float normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x80 ; continue ; } ; value = lrintf (scaled_value) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; ucptr [3] = value >> 24 ; } ; } /* f2lei_clip_array */ static sf_count_t pcm_write_f2lei (SF_PRIVATE *psf, float *ptr, sf_count_t len) { void (*convert) (float *, int *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? f2lei_clip_array : f2lei_array ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (int*) (psf->buffer), writecount, psf->norm_float) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_f2lei */ /*============================================================================== */ static void d2sc_array (double *src, signed char *dest, int count, int normalize) { double normfact ; normfact = normalize ? (1.0 * 0x7F) : 1.0 ; while (count) { count -- ; dest [count] = lrint (src [count] * normfact) ; } ; } /* d2sc_array */ static void d2sc_clip_array (double *src, signed char *dest, int count, int normalize) { double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; while (count) { count -- ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { dest [count] = 127 ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { dest [count] = -128 ; continue ; } ; dest [count] = lrintf (scaled_value) >> 24 ; } ; } /* d2sc_clip_array */ static sf_count_t pcm_write_d2sc (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, signed char *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2sc_clip_array : d2sc_array ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (signed char*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2sc */ /*============================================================================== */ static void d2uc_array (double *src, unsigned char *dest, int count, int normalize) { double normfact ; normfact = normalize ? (1.0 * 0x7F) : 1.0 ; while (count) { count -- ; dest [count] = lrint (src [count] * normfact) + 128 ; } ; } /* d2uc_array */ static void d2uc_clip_array (double *src, unsigned char *dest, int count, int normalize) { double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x1000000) ; while (count) { count -- ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { dest [count] = 255 ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { dest [count] = 0 ; continue ; } ; dest [count] = (lrint (src [count] * normfact) >> 24) + 128 ; } ; } /* d2uc_clip_array */ static sf_count_t pcm_write_d2uc (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, unsigned char *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2uc_clip_array : d2uc_array ; bufferlen = sizeof (psf->buffer) / sizeof (unsigned char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (unsigned char*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (unsigned char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2uc */ /*============================================================================== */ static void d2bes_array (double *src, short *dest, int count, int normalize) { unsigned char *ucptr ; short value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; value = lrint (src [count] * normfact) ; ucptr [1] = value ; ucptr [0] = value >> 8 ; } ; } /* d2bes_array */ static void d2bes_clip_array (double *src, short *dest, int count, int normalize) { unsigned char *ucptr ; double normfact, scaled_value ; int value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [1] = value >> 16 ; ucptr [0] = value >> 24 ; } ; } /* d2bes_clip_array */ static sf_count_t pcm_write_d2bes (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, short *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2bes_clip_array : d2bes_array ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (short*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2bes */ /*============================================================================== */ static void d2les_array (double *src, short *dest, int count, int normalize) { unsigned char *ucptr ; short value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; value = lrint (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; } ; } /* d2les_array */ static void d2les_clip_array (double *src, short *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x10000) ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [0] = value >> 16 ; ucptr [1] = value >> 24 ; } ; } /* d2les_clip_array */ static sf_count_t pcm_write_d2les (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, short *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2les_clip_array : d2les_array ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (short*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2les */ /*============================================================================== */ static void d2let_array (double *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = lrint (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; } ; } /* d2let_array */ static void d2let_clip_array (double *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0xFF ; ucptr [2] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [0] = value >> 8 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 24 ; } ; } /* d2let_clip_array */ static sf_count_t pcm_write_d2let (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, tribyte *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2let_clip_array : d2let_array ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (tribyte*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2let */ /*============================================================================== */ static void d2bet_array (double *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = lrint (src [count] * normfact) ; ucptr [2] = value ; ucptr [1] = value >> 8 ; ucptr [0] = value >> 16 ; } ; } /* d2bet_array */ static void d2bet_clip_array (double *src, tribyte *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : (1.0 * 0x100) ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [2] = 0xFF ; ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [2] = 0x00 ; ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [2] = value >> 8 ; ucptr [1] = value >> 16 ; ucptr [0] = value >> 24 ; } ; } /* d2bet_clip_array */ static sf_count_t pcm_write_d2bet (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, tribyte *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2bet_clip_array : d2bet_array ; bufferlen = sizeof (psf->buffer) / SIZEOF_TRIBYTE ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (tribyte*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, SIZEOF_TRIBYTE, writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2bet */ /*============================================================================== */ static void d2bei_array (double *src, int *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; value = lrint (src [count] * normfact) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; ucptr [3] = value ; } ; } /* d2bei_array */ static void d2bei_clip_array (double *src, int *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [3] = 0xFF ; ucptr [2] = 0xFF ; ucptr [1] = 0xFF ; ucptr [0] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [3] = 0x00 ; ucptr [2] = 0x00 ; ucptr [1] = 0x00 ; ucptr [0] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [0] = value >> 24 ; ucptr [1] = value >> 16 ; ucptr [2] = value >> 8 ; ucptr [3] = value ; } ; } /* d2bei_clip_array */ static sf_count_t pcm_write_d2bei (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, int *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2bei_clip_array : d2bei_array ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (int*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2bei */ /*============================================================================== */ static void d2lei_array (double *src, int *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact ; normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; value = lrint (src [count] * normfact) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; ucptr [3] = value >> 24 ; } ; } /* d2lei_array */ static void d2lei_clip_array (double *src, int *dest, int count, int normalize) { unsigned char *ucptr ; int value ; double normfact, scaled_value ; normfact = normalize ? (8.0 * 0x10000000) : 1.0 ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; scaled_value = src [count] * normfact ; if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF)) { ucptr [0] = 0xFF ; ucptr [1] = 0xFF ; ucptr [2] = 0xFF ; ucptr [3] = 0x7F ; continue ; } ; if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000)) { ucptr [0] = 0x00 ; ucptr [1] = 0x00 ; ucptr [2] = 0x00 ; ucptr [3] = 0x80 ; continue ; } ; value = lrint (scaled_value) ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; ucptr [3] = value >> 24 ; } ; } /* d2lei_clip_array */ static sf_count_t pcm_write_d2lei (SF_PRIVATE *psf, double *ptr, sf_count_t len) { void (*convert) (double *, int *, int, int) ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; convert = (psf->add_clipping) ? d2lei_clip_array : d2lei_array ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; convert (ptr + total, (int*) (psf->buffer), writecount, psf->norm_double) ; thiswrite = psf_fwrite (psf->buffer, sizeof (int), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* pcm_write_d2lei */ /*============================================================================== */ static void sc2s_array (signed char *src, int count, short *dest) { while (count) { count -- ; dest [count] = src [count] << 8 ; } ; } /* sc2s_array */ static void uc2s_array (unsigned char *src, int count, short *dest) { while (count) { count -- ; dest [count] = (((short) src [count]) - 0x80) << 8 ; } ; } /* uc2s_array */ static void let2s_array (tribyte *src, int count, short *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; dest [count] = LET2H_SHORT_PTR (ucptr) ; } ; } /* let2s_array */ static void bet2s_array (tribyte *src, int count, short *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; dest [count] = BET2H_SHORT_PTR (ucptr) ; } ; } /* bet2s_array */ static void lei2s_array (int *src, int count, short *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; dest [count] = LEI2H_SHORT_PTR (ucptr) ; } ; } /* lei2s_array */ static void bei2s_array (int *src, int count, short *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; dest [count] = BEI2H_SHORT_PTR (ucptr) ; } ; } /* bei2s_array */ /*----------------------------------------------------------------------------------------------- */ static void sc2i_array (signed char *src, int count, int *dest) { while (count) { count -- ; dest [count] = ((int) src [count]) << 24 ; } ; } /* sc2i_array */ static void uc2i_array (unsigned char *src, int count, int *dest) { while (count) { count -- ; dest [count] = (((int) src [count]) - 128) << 24 ; } ; } /* uc2i_array */ static void bes2i_array (short *src, int count, int *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; dest [count] = BES2H_INT_PTR (ucptr) ; } ; } /* bes2i_array */ static void les2i_array (short *src, int count, int *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; dest [count] = LES2H_INT_PTR (ucptr) ; } ; } /* les2i_array */ static void bet2i_array (tribyte *src, int count, int *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; dest [count] = BET2H_INT_PTR (ucptr) ; } ; } /* bet2i_array */ static void let2i_array (tribyte *src, int count, int *dest) { unsigned char *ucptr ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; dest [count] = LET2H_INT_PTR (ucptr) ; } ; } /* let2i_array */ /*----------------------------------------------------------------------------------------------- */ static void sc2f_array (signed char *src, int count, float *dest, float normfact) { while (count) { count -- ; dest [count] = ((float) src [count]) * normfact ; } ; } /* sc2f_array */ static void uc2f_array (unsigned char *src, int count, float *dest, float normfact) { while (count) { count -- ; dest [count] = (((float) src [count]) - 128.0) * normfact ; } ; } /* uc2f_array */ static void les2f_array (short *src, int count, float *dest, float normfact) { short value ; while (count) { count -- ; value = src [count] ; value = LES2H_SHORT (value) ; dest [count] = ((float) value) * normfact ; } ; } /* les2f_array */ static void bes2f_array (short *src, int count, float *dest, float normfact) { short value ; while (count) { count -- ; value = src [count] ; value = BES2H_SHORT (value) ; dest [count] = ((float) value) * normfact ; } ; } /* bes2f_array */ static void let2f_array (tribyte *src, int count, float *dest, float normfact) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = LET2H_INT_PTR (ucptr) ; dest [count] = ((float) value) * normfact ; } ; } /* let2f_array */ static void bet2f_array (tribyte *src, int count, float *dest, float normfact) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = BET2H_INT_PTR (ucptr) ; dest [count] = ((float) value) * normfact ; } ; } /* bet2f_array */ static void lei2f_array (int *src, int count, float *dest, float normfact) { int value ; while (count) { count -- ; value = src [count] ; value = LEI2H_INT (value) ; dest [count] = ((float) value) * normfact ; } ; } /* lei2f_array */ static void bei2f_array (int *src, int count, float *dest, float normfact) { int value ; while (count) { count -- ; value = src [count] ; value = BEI2H_INT (value) ; dest [count] = ((float) value) * normfact ; } ; } /* bei2f_array */ /*----------------------------------------------------------------------------------------------- */ static void sc2d_array (signed char *src, int count, double *dest, double normfact) { while (count) { count -- ; dest [count] = ((double) src [count]) * normfact ; } ; } /* sc2d_array */ static void uc2d_array (unsigned char *src, int count, double *dest, double normfact) { while (count) { count -- ; dest [count] = (((double) src [count]) - 128.0) * normfact ; } ; } /* uc2d_array */ static void les2d_array (short *src, int count, double *dest, double normfact) { short value ; while (count) { count -- ; value = src [count] ; value = LES2H_SHORT (value) ; dest [count] = ((double) value) * normfact ; } ; } /* les2d_array */ static void bes2d_array (short *src, int count, double *dest, double normfact) { short value ; while (count) { count -- ; value = src [count] ; value = BES2H_SHORT (value) ; dest [count] = ((double) value) * normfact ; } ; } /* bes2d_array */ static void let2d_array (tribyte *src, int count, double *dest, double normfact) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = LET2H_INT_PTR (ucptr) ; dest [count] = ((double) value) * normfact ; } ; } /* let2d_array */ static void bet2d_array (tribyte *src, int count, double *dest, double normfact) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) src) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = (ucptr [0] << 24) | (ucptr [1] << 16) | (ucptr [2] << 8) ; dest [count] = ((double) value) * normfact ; } ; } /* bet2d_array */ static void lei2d_array (int *src, int count, double *dest, double normfact) { int value ; while (count) { count -- ; value = src [count] ; value = LEI2H_INT (value) ; dest [count] = ((double) value) * normfact ; } ; } /* lei2d_array */ static void bei2d_array (int *src, int count, double *dest, double normfact) { int value ; while (count) { count -- ; value = src [count] ; value = BEI2H_INT (value) ; dest [count] = ((double) value) * normfact ; } ; } /* bei2d_array */ /*----------------------------------------------------------------------------------------------- */ static void s2sc_array (short *src, signed char *dest, int count) { while (count) { count -- ; dest [count] = src [count] >> 8 ; } ; } /* s2sc_array */ static void s2uc_array (short *src, unsigned char *dest, int count) { while (count) { count -- ; dest [count] = (src [count] >> 8) + 0x80 ; } ; } /* s2uc_array */ static void s2let_array (short *src, tribyte *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; ucptr [0] = 0 ; ucptr [1] = src [count] ; ucptr [2] = src [count] >> 8 ; } ; } /* s2let_array */ static void s2bet_array (short *src, tribyte *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; ucptr [2] = 0 ; ucptr [1] = src [count] ; ucptr [0] = src [count] >> 8 ; } ; } /* s2bet_array */ static void s2lei_array (short *src, int *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; ucptr [0] = 0 ; ucptr [1] = 0 ; ucptr [2] = src [count] ; ucptr [3] = src [count] >> 8 ; } ; } /* s2lei_array */ static void s2bei_array (short *src, int *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 4 * count ; while (count) { count -- ; ucptr -= 4 ; ucptr [0] = src [count] >> 8 ; ucptr [1] = src [count] ; ucptr [2] = 0 ; ucptr [3] = 0 ; } ; } /* s2bei_array */ /*----------------------------------------------------------------------------------------------- */ static void i2sc_array (int *src, signed char *dest, int count) { while (count) { count -- ; dest [count] = (src [count] >> 24) ; } ; } /* i2sc_array */ static void i2uc_array (int *src, unsigned char *dest, int count) { while (count) { count -- ; dest [count] = ((src [count] >> 24) + 128) ; } ; } /* i2uc_array */ static void i2bes_array (int *src, short *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; ucptr [0] = src [count] >> 24 ; ucptr [1] = src [count] >> 16 ; } ; } /* i2bes_array */ static void i2les_array (int *src, short *dest, int count) { unsigned char *ucptr ; ucptr = ((unsigned char*) dest) + 2 * count ; while (count) { count -- ; ucptr -= 2 ; ucptr [0] = src [count] >> 16 ; ucptr [1] = src [count] >> 24 ; } ; } /* i2les_array */ static void i2let_array (int *src, tribyte *dest, int count) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = src [count] >> 8 ; ucptr [0] = value ; ucptr [1] = value >> 8 ; ucptr [2] = value >> 16 ; } ; } /* i2let_array */ static void i2bet_array (int *src, tribyte *dest, int count) { unsigned char *ucptr ; int value ; ucptr = ((unsigned char*) dest) + 3 * count ; while (count) { count -- ; ucptr -= 3 ; value = src [count] >> 8 ; ucptr [2] = value ; ucptr [1] = value >> 8 ; ucptr [0] = value >> 16 ; } ; } /* i2bet_array */ /*----------------------------------------------------------------------------------------------- */ /*----------------------------------------------------------------------------------------------- */ /*============================================================================== */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: d8bc7c0e-1e2f-4ff3-a28f-10ce1fbade3b */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* 4.2.0 .. 4.2.3 PREPROCESSING SECTION * * After A-law to linear conversion (or directly from the * Ato D converter) the following scaling is assumed for * input to the RPE-LTP algorithm: * * in: 0.1.....................12 * S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.* * * Where S is the sign bit, v a valid bit, and * a "don't care" bit. * The original signal is called sop[..] * * out: 0.1................... 12 * S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0 */ void Gsm_Preprocess ( struct gsm_state * S, word * s, word * so ) /* [0..159] IN/OUT */ { word z1 = S->z1; longword L_z2 = S->L_z2; word mp = S->mp; word s1; longword L_s2; longword L_temp; word msp, lsp; word SO; register int k = 160; while (k--) { /* 4.2.1 Downscaling of the input signal */ SO = SASR_W( *s, 3 ) << 2; s++; assert (SO >= -0x4000); /* downscaled by */ assert (SO <= 0x3FFC); /* previous routine. */ /* 4.2.2 Offset compensation * * This part implements a high-pass filter and requires extended * arithmetic precision for the recursive part of this filter. * The input of this procedure is the array so[0...159] and the * output the array sof[ 0...159 ]. */ /* Compute the non-recursive part */ s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */ z1 = SO; assert(s1 != MIN_WORD); /* Compute the recursive part */ L_s2 = s1; L_s2 <<= 15; /* Execution of a 31 bv 16 bits multiplication */ msp = SASR_L( L_z2, 15 ); lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */ L_s2 += GSM_MULT_R( lsp, 32735 ); L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/ L_z2 = GSM_L_ADD( L_temp, L_s2 ); /* Compute sof[k] with rounding */ L_temp = GSM_L_ADD( L_z2, 16384 ); /* 4.2.3 Preemphasis */ msp = GSM_MULT_R( mp, -28180 ); mp = SASR_L( L_temp, 15 ); *so++ = GSM_ADD( mp, msp ); } S->z1 = z1; S->L_z2 = L_z2; S->mp = mp; } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: b760b0d9-3a05-4da3-9dc9-441ffb905d87 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define PVF1_MARKER (MAKE_MARKER ('P', 'V', 'F', '1')) /*------------------------------------------------------------------------------ ** Private static functions. */ static int pvf_close (SF_PRIVATE *psf) ; static int pvf_write_header (SF_PRIVATE *psf, int calc_length) ; static int pvf_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int pvf_open (SF_PRIVATE *psf) { int subformat ; int error = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = pvf_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PVF) return SFE_BAD_OPEN_FORMAT ; psf->endian = SF_ENDIAN_BIG ; if (pvf_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = pvf_write_header ; } ; psf->close = pvf_close ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */ case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */ case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */ error = pcm_init (psf) ; break ; default : break ; } ; return error ; } /* pvf_open */ /*------------------------------------------------------------------------------ */ static int pvf_close (SF_PRIVATE *psf) { psf = psf ; return 0 ; } /* pvf_close */ static int pvf_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; if (psf->pipeoffset > 0) return 0 ; calc_length = calc_length ; /* Avoid a compiler warning. */ current = psf_ftell (psf) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; LSF_SNPRINTF ((char*) psf->header, sizeof (psf->header), "PVF1\n%d %d %d\n", psf->sf.channels, psf->sf.samplerate, psf->bytewidth * 8) ; psf->headindex = strlen ((char*) psf->header) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* pvf_write_header */ static int pvf_read_header (SF_PRIVATE *psf) { char buffer [32] ; int marker, channels, samplerate, bitwidth ; psf_binheader_readf (psf, "pmj", 0, &marker, 1) ; psf_log_printf (psf, "%M\n", marker) ; if (marker != PVF1_MARKER) return SFE_PVF_NO_PVF1 ; /* Grab characters up until a newline which is replaced by an EOS. */ psf_binheader_readf (psf, "G", buffer, sizeof (buffer)) ; if (sscanf (buffer, "%d %d %d", &channels, &samplerate, &bitwidth) != 3) return SFE_PVF_BAD_HEADER ; psf_log_printf (psf, " Channels : %d\n Sample rate : %d\n Bit width : %d\n", channels, samplerate, bitwidth) ; psf->sf.channels = channels ; psf->sf.samplerate = samplerate ; switch (bitwidth) { case 8 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case 16 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; case 32 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; break ; default : return SFE_PVF_BAD_BITWIDTH ; } ; psf->dataoffset = psf_ftell (psf) ; psf_log_printf (psf, " Data Offset : %D\n", psf->dataoffset) ; psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->close = pvf_close ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* pvf_read_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 20a26761-8bc1-41d7-b1f3-9793bf3d9864 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include /*------------------------------------------------------------------------------ ** Public function. */ int raw_open (SF_PRIVATE *psf) { int subformat, error = SFE_NO_ERROR ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) psf->endian = SF_ENDIAN_BIG ; else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)) psf->endian = SF_ENDIAN_LITTLE ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->dataoffset = 0 ; psf->datalength = psf->filelength ; switch (subformat) { case SF_FORMAT_PCM_S8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_U8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; case SF_FORMAT_GSM610 : error = gsm610_init (psf) ; break ; /* Lite remove start */ case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; case SF_FORMAT_DWVW_12 : error = dwvw_init (psf, 12) ; break ; case SF_FORMAT_DWVW_16 : error = dwvw_init (psf, 16) ; break ; case SF_FORMAT_DWVW_24 : error = dwvw_init (psf, 24) ; break ; case SF_FORMAT_VOX_ADPCM : error = vox_adpcm_init (psf) ; break ; /* Lite remove end */ default : return SFE_BAD_OPEN_FORMAT ; } ; return error ; } /* raw_open */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: f0066de7-d6ce-4f36-a1e0-e475c07d4e1a */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* 4.2.13 .. 4.2.17 RPE ENCODING SECTION */ /* 4.2.13 */ static void Weighting_filter ( register word * e, /* signal [-5..0.39.44] IN */ word * x /* signal [0..39] OUT */ ) /* * The coefficients of the weighting filter are stored in a table * (see table 4.4). The following scaling is used: * * H[0..10] = integer( real_H[ 0..10] * 8192 ); */ { /* word wt[ 50 ]; */ register longword L_result; register int k /* , i */ ; /* Initialization of a temporary working array wt[0...49] */ /* for (k = 0; k <= 4; k++) wt[k] = 0; * for (k = 5; k <= 44; k++) wt[k] = *e++; * for (k = 45; k <= 49; k++) wt[k] = 0; * * (e[-5..-1] and e[40..44] are allocated by the caller, * are initially zero and are not written anywhere.) */ e -= 5; /* Compute the signal x[0..39] */ for (k = 0; k <= 39; k++) { L_result = 8192 >> 1; /* for (i = 0; i <= 10; i++) { * L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] ); * L_result = GSM_L_ADD( L_result, L_temp ); * } */ #undef rpeSTEP #define rpeSTEP( i, H ) (e[ k + i ] * (longword)H) /* Every one of these multiplications is done twice -- * but I don't see an elegant way to optimize this. * Do you? */ #ifdef STUPID_COMPILER L_result += rpeSTEP( 0, -134 ) ; L_result += rpeSTEP( 1, -374 ) ; /* + rpeSTEP( 2, 0 ) */ L_result += rpeSTEP( 3, 2054 ) ; L_result += rpeSTEP( 4, 5741 ) ; L_result += rpeSTEP( 5, 8192 ) ; L_result += rpeSTEP( 6, 5741 ) ; L_result += rpeSTEP( 7, 2054 ) ; /* + rpeSTEP( 8, 0 ) */ L_result += rpeSTEP( 9, -374 ) ; L_result += rpeSTEP( 10, -134 ) ; #else L_result += rpeSTEP( 0, -134 ) + rpeSTEP( 1, -374 ) /* + rpeSTEP( 2, 0 ) */ + rpeSTEP( 3, 2054 ) + rpeSTEP( 4, 5741 ) + rpeSTEP( 5, 8192 ) + rpeSTEP( 6, 5741 ) + rpeSTEP( 7, 2054 ) /* + rpeSTEP( 8, 0 ) */ + rpeSTEP( 9, -374 ) + rpeSTEP(10, -134 ) ; #endif /* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *) * L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *) * * x[k] = SASR( L_result, 16 ); */ /* 2 adds vs. >>16 => 14, minus one shift to compensate for * those we lost when replacing L_MULT by '*'. */ L_result = SASR_L( L_result, 13 ); x[k] = ( L_result < MIN_WORD ? MIN_WORD : (L_result > MAX_WORD ? MAX_WORD : L_result )); } } /* 4.2.14 */ static void RPE_grid_selection ( word * x, /* [0..39] IN */ word * xM, /* [0..12] OUT */ word * Mc_out /* OUT */ ) /* * The signal x[0..39] is used to select the RPE grid which is * represented by Mc. */ { /* register word temp1; */ register int /* m, */ i; register longword L_result, L_temp; longword EM; /* xxx should be L_EM? */ word Mc; longword L_common_0_3; EM = 0; Mc = 0; /* for (m = 0; m <= 3; m++) { * L_result = 0; * * * for (i = 0; i <= 12; i++) { * * temp1 = SASR_W( x[m + 3*i], 2 ); * * assert(temp1 != MIN_WORD); * * L_temp = GSM_L_MULT( temp1, temp1 ); * L_result = GSM_L_ADD( L_temp, L_result ); * } * * if (L_result > EM) { * Mc = m; * EM = L_result; * } * } */ #undef rpeSTEP #define rpeSTEP( m, i ) L_temp = SASR_W( x[m + 3 * i], 2 ); \ L_result += L_temp * L_temp; /* common part of 0 and 3 */ L_result = 0; rpeSTEP( 0, 1 ); rpeSTEP( 0, 2 ); rpeSTEP( 0, 3 ); rpeSTEP( 0, 4 ); rpeSTEP( 0, 5 ); rpeSTEP( 0, 6 ); rpeSTEP( 0, 7 ); rpeSTEP( 0, 8 ); rpeSTEP( 0, 9 ); rpeSTEP( 0, 10); rpeSTEP( 0, 11); rpeSTEP( 0, 12); L_common_0_3 = L_result; /* i = 0 */ rpeSTEP( 0, 0 ); L_result <<= 1; /* implicit in L_MULT */ EM = L_result; /* i = 1 */ L_result = 0; rpeSTEP( 1, 0 ); rpeSTEP( 1, 1 ); rpeSTEP( 1, 2 ); rpeSTEP( 1, 3 ); rpeSTEP( 1, 4 ); rpeSTEP( 1, 5 ); rpeSTEP( 1, 6 ); rpeSTEP( 1, 7 ); rpeSTEP( 1, 8 ); rpeSTEP( 1, 9 ); rpeSTEP( 1, 10); rpeSTEP( 1, 11); rpeSTEP( 1, 12); L_result <<= 1; if (L_result > EM) { Mc = 1; EM = L_result; } /* i = 2 */ L_result = 0; rpeSTEP( 2, 0 ); rpeSTEP( 2, 1 ); rpeSTEP( 2, 2 ); rpeSTEP( 2, 3 ); rpeSTEP( 2, 4 ); rpeSTEP( 2, 5 ); rpeSTEP( 2, 6 ); rpeSTEP( 2, 7 ); rpeSTEP( 2, 8 ); rpeSTEP( 2, 9 ); rpeSTEP( 2, 10); rpeSTEP( 2, 11); rpeSTEP( 2, 12); L_result <<= 1; if (L_result > EM) { Mc = 2; EM = L_result; } /* i = 3 */ L_result = L_common_0_3; rpeSTEP( 3, 12 ); L_result <<= 1; if (L_result > EM) { Mc = 3; EM = L_result; } /**/ /* Down-sampling by a factor 3 to get the selected xM[0..12] * RPE sequence. */ for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i]; *Mc_out = Mc; } /* 4.12.15 */ static void APCM_quantization_xmaxc_to_exp_mant ( word xmaxc, /* IN */ word * expon_out, /* OUT */ word * mant_out ) /* OUT */ { word expon, mant; /* Compute expononent and mantissa of the decoded version of xmaxc */ expon = 0; if (xmaxc > 15) expon = SASR_W(xmaxc, 3) - 1; mant = xmaxc - (expon << 3); if (mant == 0) { expon = -4; mant = 7; } else { while (mant <= 7) { mant = mant << 1 | 1; expon--; } mant -= 8; } assert( expon >= -4 && expon <= 6 ); assert( mant >= 0 && mant <= 7 ); *expon_out = expon; *mant_out = mant; } static void APCM_quantization ( word * xM, /* [0..12] IN */ word * xMc, /* [0..12] OUT */ word * mant_out, /* OUT */ word * expon_out, /* OUT */ word * xmaxc_out /* OUT */ ) { int i, itest; word xmax, xmaxc, temp, temp1, temp2; word expon, mant; /* Find the maximum absolute value xmax of xM[0..12]. */ xmax = 0; for (i = 0; i <= 12; i++) { temp = xM[i]; temp = GSM_ABS(temp); if (temp > xmax) xmax = temp; } /* Qantizing and coding of xmax to get xmaxc. */ expon = 0; temp = SASR_W( xmax, 9 ); itest = 0; for (i = 0; i <= 5; i++) { itest |= (temp <= 0); temp = SASR_W( temp, 1 ); assert(expon <= 5); if (itest == 0) expon++; /* expon = add (expon, 1) */ } assert(expon <= 6 && expon >= 0); temp = expon + 5; assert(temp <= 11 && temp >= 0); xmaxc = gsm_add( SASR_W(xmax, temp), (word) (expon << 3) ); /* Quantizing and coding of the xM[0..12] RPE sequence * to get the xMc[0..12] */ APCM_quantization_xmaxc_to_exp_mant( xmaxc, &expon, &mant ); /* This computation uses the fact that the decoded version of xmaxc * can be calculated by using the expononent and the mantissa part of * xmaxc (logarithmic table). * So, this method avoids any division and uses only a scaling * of the RPE samples by a function of the expononent. A direct * multiplication by the inverse of the mantissa (NRFAC[0..7] * found in table 4.5) gives the 3 bit coded version xMc[0..12] * of the RPE samples. */ /* Direct computation of xMc[0..12] using table 4.5 */ assert( expon <= 4096 && expon >= -4096); assert( mant >= 0 && mant <= 7 ); temp1 = 6 - expon; /* normalization by the expononent */ temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */ for (i = 0; i <= 12; i++) { assert(temp1 >= 0 && temp1 < 16); temp = xM[i] << temp1; temp = GSM_MULT( temp, temp2 ); temp = SASR_W(temp, 12); xMc[i] = temp + 4; /* see note below */ } /* NOTE: This equation is used to make all the xMc[i] positive. */ *mant_out = mant; *expon_out = expon; *xmaxc_out = xmaxc; } /* 4.2.16 */ static void APCM_inverse_quantization ( register word * xMc, /* [0..12] IN */ word mant, word expon, register word * xMp) /* [0..12] OUT */ /* * This part is for decoding the RPE sequence of coded xMc[0..12] * samples to obtain the xMp[0..12] array. Table 4.6 is used to get * the mantissa of xmaxc (FAC[0..7]). */ { int i; word temp, temp1, temp2, temp3; assert( mant >= 0 && mant <= 7 ); temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */ temp2 = gsm_sub( 6, expon ); /* see 4.2-15 for exp */ temp3 = gsm_asl( 1, gsm_sub( temp2, 1 )); for (i = 13; i--;) { assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */ /* temp = gsm_sub( *xMc++ << 1, 7 ); */ temp = (*xMc++ << 1) - 7; /* restore sign */ assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */ temp <<= 12; /* 16 bit signed */ temp = GSM_MULT_R( temp1, temp ); temp = GSM_ADD( temp, temp3 ); *xMp++ = gsm_asr( temp, temp2 ); } } /* 4.2.17 */ static void RPE_grid_positioning ( word Mc, /* grid position IN */ register word * xMp, /* [0..12] IN */ register word * ep /* [0..39] OUT */ ) /* * This procedure computes the reconstructed long term residual signal * ep[0..39] for the LTP analysis filter. The inputs are the Mc * which is the grid position selection and the xMp[0..12] decoded * RPE samples which are upsampled by a factor of 3 by inserting zero * values. */ { int i = 13; assert(0 <= Mc && Mc <= 3); switch (Mc) { case 3: *ep++ = 0; case 2: do { *ep++ = 0; case 1: *ep++ = 0; case 0: *ep++ = *xMp++; } while (--i); } while (++Mc < 4) *ep++ = 0; /* int i, k; for (k = 0; k <= 39; k++) ep[k] = 0; for (i = 0; i <= 12; i++) { ep[ Mc + (3*i) ] = xMp[i]; } */ } /* 4.2.18 */ /* This procedure adds the reconstructed long term residual signal * ep[0..39] to the estimated signal dpp[0..39] from the long term * analysis filter to compute the reconstructed short term residual * signal dp[-40..-1]; also the reconstructed short term residual * array dp[-120..-41] is updated. */ #if 0 /* Has been inlined in code.c */ void Gsm_Update_of_reconstructed_short_time_residual_signal ( word * dpp, /* [0...39] IN */ word * ep, /* [0...39] IN */ word * dp) /* [-120...-1] IN/OUT */ { int k; for (k = 0; k <= 79; k++) dp[ -120 + k ] = dp[ -80 + k ]; for (k = 0; k <= 39; k++) dp[ -40 + k ] = gsm_add( ep[k], dpp[k] ); } #endif /* Has been inlined in code.c */ void Gsm_RPE_Encoding ( /*-struct gsm_state * S,-*/ word * e, /* -5..-1][0..39][40..44 IN/OUT */ word * xmaxc, /* OUT */ word * Mc, /* OUT */ word * xMc) /* [0..12] OUT */ { word x[40]; word xM[13], xMp[13]; word mant, expon; Weighting_filter(e, x); RPE_grid_selection(x, xM, Mc); APCM_quantization( xM, xMc, &mant, &expon, xmaxc); APCM_inverse_quantization( xMc, mant, expon, xMp); RPE_grid_positioning( *Mc, xMp, e ); } void Gsm_RPE_Decoding ( /*-struct gsm_state * S,-*/ word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */ word * erp /* [0..39] OUT */ ) { word expon, mant; word xMp[ 13 ]; APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &expon, &mant ); APCM_inverse_quantization( xMcr, mant, expon, xMp ); RPE_grid_positioning( Mcr, xMp, erp ); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 82005b9e-1560-4e94-9ddb-00cb14867295 */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int rx2_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* rx2_open */ #else /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define CAT_MARKER (MAKE_MARKER ('C', 'A', 'T', ' ')) #define GLOB_MARKER (MAKE_MARKER ('G', 'L', 'O', 'B')) #define RECY_MARKER (MAKE_MARKER ('R', 'E', 'C', 'Y')) #define SLCL_MARKER (MAKE_MARKER ('S', 'L', 'C', 'L')) #define SLCE_MARKER (MAKE_MARKER ('S', 'L', 'C', 'E')) #define DEVL_MARKER (MAKE_MARKER ('D', 'E', 'V', 'L')) #define TRSH_MARKER (MAKE_MARKER ('T', 'R', 'S', 'H')) #define EQ_MARKER (MAKE_MARKER ('E', 'Q', ' ', ' ')) #define COMP_MARKER (MAKE_MARKER ('C', 'O', 'M', 'P')) #define SINF_MARKER (MAKE_MARKER ('S', 'I', 'N', 'F')) #define SDAT_MARKER (MAKE_MARKER ('S', 'D', 'A', 'T')) /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ /*------------------------------------------------------------------------------ * Private static functions. */ static int rx2_close (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public functions. */ int rx2_open (SF_PRIVATE *psf) { static char *marker_type [4] = { "Original Enabled", "Enabled Hidden", "Additional/PencilTool", "Disabled" } ; int error, marker, length, glob_offset, slce_count, frames ; int sdat_length = 0, slce_total = 0 ; int n_channels ; /* So far only doing read. */ psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ; if (marker != CAT_MARKER) { psf_log_printf (psf, "length : %d\n", length) ; return -1000 ; } ; if (length != psf->filelength - 8) psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ; else psf_log_printf (psf, "%M : %d\n", marker, length) ; /* 'REX2' marker */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "%M", marker) ; /* 'HEAD' marker */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "%M\n", marker) ; /* Grab 'GLOB' offset. */ psf_binheader_readf (psf, "E4", &glob_offset) ; glob_offset += 0x14 ; /* Add the current file offset. */ /* Jump to offset 0x30 */ psf_binheader_readf (psf, "p", 0x30) ; /* Get name length */ length = 0 ; psf_binheader_readf (psf, "1", &length) ; if (length >= SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ; return -1001 ; } memset (psf->buffer, 0, SIGNED_SIZEOF (psf->buffer)) ; psf_binheader_readf (psf, "b", psf->buffer, length) ; psf_log_printf (psf, " Text : \"%s\"\n", psf->buffer) ; /* Jump to GLOB offset position. */ if (glob_offset & 1) glob_offset ++ ; psf_binheader_readf (psf, "p", glob_offset) ; slce_count = 0 ; /* GLOB */ while (1) { psf_binheader_readf (psf, "m", &marker) ; if (marker != SLCE_MARKER && slce_count > 0) { psf_log_printf (psf, " SLCE count : %d\n", slce_count) ; slce_count = 0 ; } switch (marker) { case GLOB_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "j", length) ; break ; case RECY_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */ break ; case CAT_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; /*-psf_binheader_readf (psf, "j", length) ;-*/ break ; case DEVL_MARKER: psf_binheader_readf (psf, "mE4", &marker, &length) ; psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ; if (length & 1) length ++ ; psf_binheader_readf (psf, "j", length) ; break ; case EQ_MARKER: case COMP_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; /* This is weird!!!! why make this (length - 1) */ if (length & 1) length ++ ; psf_binheader_readf (psf, "j", length) ; break ; case SLCL_MARKER: psf_log_printf (psf, " %M\n (Offset, Next Offset, Type)\n", marker) ; slce_count = 0 ; break ; case SLCE_MARKER: { int len [4], indx ; psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ; indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ; if (len [2] == 1) { if (indx != 1) indx = 3 ; /* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */ psf_log_printf (psf, " %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ; } else { slce_total += len [2] ; psf_log_printf (psf, " %M : (%6d, SLCE_next_ofs:%d, ?: 0x%X, %s)\n", marker, len [1], len [2], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ; } ; slce_count ++ ; } ; break ; case SINF_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "E2", &n_channels) ; n_channels = (n_channels & 0x0000FF00) >> 8 ; psf_log_printf (psf, " Channels : %d\n", n_channels) ; psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ; psf->sf.frames = frames ; psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ; psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " ??????????? : %d\n", length) ; psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " ??????????? : %d\n", length) ; break ; case SDAT_MARKER: psf_binheader_readf (psf, "E4", &length) ; sdat_length = length ; /* Get the current offset. */ psf->dataoffset = psf_binheader_readf (psf, NULL) ; if (psf->dataoffset + length != psf->filelength) psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ; else psf_log_printf (psf, " %M : %d\n", marker, length) ; break ; default : psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ; return -1003 ; break ; } ; /* SDAT always last marker in file. */ if (marker == SDAT_MARKER) break ; } ; puts (psf->logbuffer) ; puts ("-----------------------------------") ; printf ("SDAT length : %d\n", sdat_length) ; printf ("SLCE count : %d\n", slce_count) ; /* Hack for zero slice count. */ if (slce_count == 0 && slce_total == 1) slce_total = frames ; printf ("SLCE samples : %d\n", slce_total) ; /* Two bytes per sample. */ printf ("Comp Ratio : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ; puts (" ") ; psf->logbuffer [0] = 0 ; /* OK, have the header although not too sure what it all means. */ psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf_fseek (psf, psf->dataoffset, SEEK_SET)) return SFE_BAD_SEEK ; psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ; psf->sf.channels = 1 ; psf->bytewidth = 2 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if ((error = dwvw_init (psf, 16))) return error ; psf->close = rx2_close ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = psf->datalength / psf->blockwidth ; /* All done. */ return 0 ; } /* rx2_open */ /*------------------------------------------------------------------------------ */ static int rx2_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE) { /* Now we know for certain the length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ } ; return 0 ; } /* rx2_close */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 7366e813-9fee-4d1f-881e-e4a691469370 */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int sd2_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* sd2_open */ #else /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f') /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ /*------------------------------------------------------------------------------ * Private static functions. */ static int sd2_close (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public functions. */ int sd2_open (SF_PRIVATE *psf) { int marker, software, rsrc_offset, len ; int rsrc_data_offset, rsrc_map_offset, rsrc_data_length, rsrc_map_length ; char slen ; float srate ; /* Read only so far. */ psf_binheader_readf (psf, "Epmmj", 0x41, &marker, &software, 14) ; if (marker != Sd2f_MARKER) { printf ("Whoops!!!\n") ; puts (psf->logbuffer) ; return SFE_INTERNAL ; } ; psf_log_printf (psf, "Marker : %M\n" "Software : %M\n", marker, software) ; /* This seems to be a constant for binhex files. */ psf->dataoffset = 0x80 ; /* All SD2 files are big endian. */ psf->endian= SF_ENDIAN_BIG ; /* ** Resource header info from: ** http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-99.html */ rsrc_offset = psf->datalength + psf->dataoffset ; if (rsrc_offset & 0x7F) rsrc_offset = rsrc_offset - (rsrc_offset & 0x7F) + psf->dataoffset ; psf_log_printf (psf, "Resource offset : 0x%X\n", rsrc_offset) ; /* Jump to the rsrc_offset fork section. */ psf_binheader_readf (psf, "Ep", rsrc_offset) ; psf_binheader_readf (psf, "E4444", &rsrc_data_offset, &rsrc_map_offset, &rsrc_data_length, &rsrc_map_length) ; rsrc_data_offset += rsrc_offset ; rsrc_map_offset += rsrc_offset ; psf_log_printf (psf, " data offset : 0x%X\n" " map offset : 0x%X\n" " data length : 0x%X\n" " map length : 0x%X\n", rsrc_data_offset, rsrc_map_offset, rsrc_data_length, rsrc_map_length) ; if (rsrc_data_offset + rsrc_data_length > rsrc_map_offset || rsrc_map_offset + rsrc_map_length > psf->filelength) { puts ("##############################") ; puts (psf->logbuffer) ; puts ("##############################") ; return SFE_INTERNAL ; } ; memset (psf->buffer, 0, sizeof (psf->buffer)) ; psf_binheader_readf (psf, "Ep41", rsrc_data_offset, &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%d", &len) == 1) psf->bytewidth = len ; } ; psf_binheader_readf (psf, "E41", &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%f", &srate) == 1) psf->sf.samplerate = srate ; } ; psf_binheader_readf (psf, "E41", &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%d", &len) == 1) psf->sf.channels = len ; } ; psf_log_printf (psf, " byte width : %d\n", psf->bytewidth) ; psf_log_printf (psf, " sample rate : %d\n", psf->sf.samplerate) ; psf_log_printf (psf, " channels : %d\n", psf->sf.channels) ; if (psf->bytewidth == 2) { psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->sf.frames = psf->datalength / psf->blockwidth ; } ; pcm_init (psf) ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; psf->close = sd2_close ; return 0 ; } /* sd2_open */ /*------------------------------------------------------------------------------ */ static int sd2_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE) { /* Now we know for certain the audio_length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ } ; return 0 ; } /* sd2_close */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 1ee183e5-6b9f-4c2c-bd0a-24f35595cefc */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /*------------------------------------------------------------------------------ */ #define SDS_DATA_OFFSET 0x15 #define SDS_BLOCK_SIZE 127 #define SDS_AUDIO_BYTES_PER_BLOCK 120 #define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2)) #define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000)) /*------------------------------------------------------------------------------ ** Typedefs. */ typedef struct tag_SDS_PRIVATE { int bitwidth, frames ; int samplesperblock, total_blocks ; int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ; int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ; int read_block, read_count ; unsigned char read_data [SDS_BLOCK_SIZE] ; int read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */ int write_block, write_count ; unsigned char write_data [SDS_BLOCK_SIZE] ; int write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */ } SDS_PRIVATE ; /*------------------------------------------------------------------------------ ** Private static functions. */ static int sds_close (SF_PRIVATE *psf) ; static int sds_write_header (SF_PRIVATE *psf, int calc_length) ; static int sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t sds_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t sds_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t sds_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t sds_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ; static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ; static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int writecount) ; /*------------------------------------------------------------------------------ ** Public function. */ int sds_open (SF_PRIVATE *psf) { SDS_PRIVATE *psds ; int subformat, error = 0 ; /* Hmmmm, need this here to pass update_header_test. */ psf->sf.frames = 0 ; if (! (psds = calloc (1, sizeof (SDS_PRIVATE)))) return SFE_MALLOC_FAILED ; psf->fdata = psds ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = sds_read_header (psf, psds))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SDS) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (sds_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = sds_write_header ; psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ; } ; if ((error = sds_init (psf, psds)) != 0) return error ; psf->seek = sds_seek ; psf->close = sds_close ; psf->blockwidth = 0 ; return error ; } /* sds_open */ /*------------------------------------------------------------------------------ */ static int sds_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { SDS_PRIVATE *psds ; if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL) { psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ; return SFE_INTERNAL ; } ; if (psds->write_count > 0) { memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ; psds->writer (psf, psds) ; } ; sds_write_header (psf, SF_TRUE) ; } ; return 0 ; } /* sds_close */ static int sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) { if (psds->bitwidth < 8 || psds->bitwidth > 28) return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ; if (psds->bitwidth < 14) { psds->reader = sds_2byte_read ; psds->writer = sds_2byte_write ; psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ; } else if (psds->bitwidth < 21) { psds->reader = sds_3byte_read ; psds->writer = sds_3byte_write ; psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ; } else { psds->reader = sds_4byte_read ; psds->writer = sds_4byte_write ; psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ; } ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { psf->read_short = sds_read_s ; psf->read_int = sds_read_i ; psf->read_float = sds_read_f ; psf->read_double = sds_read_d ; /* Read first block. */ psds->reader (psf, psds) ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->write_short = sds_write_s ; psf->write_int = sds_write_i ; psf->write_float = sds_write_f ; psf->write_double = sds_write_d ; } ; return 0 ; } /* sds_init */ static int sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char channel, bitwidth, loop_type, byte ; unsigned short sample_no, marker ; unsigned int samp_period, data_length, sustain_loop_start, sustain_loop_end ; int bytesread, blockcount ; /* Set position to start of file to begin reading header. */ bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ; if (marker != 0xF07E || byte != 0x01) return SFE_SDS_NOT_SDS ; psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel : %d\n", channel) ; bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ; sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ; samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ; psds->bitwidth = bitwidth ; psf->sf.samplerate = 1000000000 / samp_period ; psf_log_printf (psf, " Sample Number : %d\n" " Bit Width : %d\n" " Sample Rate : %d\n", sample_no, psds->bitwidth, psf->sf.samplerate) ; bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ; data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ; sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ; sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ; psf_log_printf (psf, " Sustain Loop\n" " Start : %d\n" " End : %d\n" " Loop Type : %d\n", sustain_loop_start, sustain_loop_end, loop_type) ; psf->dataoffset = SDS_DATA_OFFSET ; psf->datalength = psf->filelength - psf->dataoffset ; if (data_length != psf->filelength - psf->dataoffset) { psf_log_printf (psf, " Datalength : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ; data_length = psf->filelength - psf->dataoffset ; } else psf_log_printf (psf, " Datalength : %d\n", data_length) ; bytesread += psf_binheader_readf (psf, "1", &byte) ; if (byte != 0xF7) psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ; for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++) { bytesread += psf_fread (&marker, 1, 2, psf) ; if (marker == 0) break ; psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ; bytesread += SDS_BLOCK_SIZE - 2 ; } ; psf_log_printf (psf, "\nBlocks : %d\n", blockcount) ; psds->total_blocks = blockcount ; psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ; psf_log_printf (psf, "Samples/Block : %d\n", psds->samplesperblock) ; psf_log_printf (psf, "Frames : %d\n", blockcount * psds->samplesperblock) ; psf->sf.frames = blockcount * psds->samplesperblock ; psds->frames = blockcount * psds->samplesperblock ; /* Always Mono */ psf->sf.channels = 1 ; psf->sf.sections = 1 ; /* ** Lie to the user about PCM bit width. Always round up to ** the next multiple of 8. */ switch ((psds->bitwidth + 7) / 8) { case 1 : psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ; break ; case 2 : psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ; break ; case 3 : psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ; break ; case 4 : psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ; break ; default : psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ; return SFE_SDS_BAD_BIT_WIDTH ; } ; psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ; return 0 ; } /* sds_read_header */ static int sds_write_header (SF_PRIVATE *psf, int calc_length) { SDS_PRIVATE *psds ; sf_count_t current ; int samp_period, data_length, sustain_loop_start, sustain_loop_end ; unsigned char loop_type = 0 ; if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL) { psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ; return SFE_INTERNAL ; } ; if (psf->pipeoffset > 0) return 0 ; current = psf_ftell (psf) ; if (calc_length) psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ; if (psds->write_count > 0) { int current_count = psds->write_count ; int current_block = psds->write_block ; psds->writer (psf, psds) ; psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ; psds->write_count = current_count ; psds->write_block = current_block ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; if (psf->is_pipe == SF_FALSE) psf_fseek (psf, 0, SEEK_SET) ; psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ; switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : psds->bitwidth = 8 ; break ; case SF_FORMAT_PCM_16 : psds->bitwidth = 16 ; break ; case SF_FORMAT_PCM_24 : psds->bitwidth = 24 ; break ; default: return SFE_SDS_BAD_BIT_WIDTH ; } ; samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ; psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ; data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ; sustain_loop_start = SDS_INT_TO_3BYTE_ENCODE (0) ; sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ; psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; psf->datalength = psds->write_block * SDS_BLOCK_SIZE ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* sds_write_header */ /*------------------------------------------------------------------------------ */ static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->read_block ++ ; psds->read_count = 0 ; if (psds->read_block * psds->samplesperblock > psds->frames) { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; return 1 ; } ; if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; } ; checksum = psds->read_data [1] ; if (checksum != 0x7E) { printf ("Error 1 : %02X\n", checksum & 0xFF) ; } for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->read_data [k] ; checksum &= 0x7F ; if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; } ; ucptr = psds->read_data + 5 ; for (k = 0 ; k < 120 ; k += 2) { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) ; psds->read_samples [k / 2] = (int) (sample - 0x80000000) ; } ; return 1 ; } /* sds_2byte_read */ static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->read_block ++ ; psds->read_count = 0 ; if (psds->read_block * psds->samplesperblock > psds->frames) { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; return 1 ; } ; if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; } ; checksum = psds->read_data [1] ; if (checksum != 0x7E) { printf ("Error 1 : %02X\n", checksum & 0xFF) ; } for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->read_data [k] ; checksum &= 0x7F ; if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; } ; ucptr = psds->read_data + 5 ; for (k = 0 ; k < 120 ; k += 3) { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ; psds->read_samples [k / 3] = (int) (sample - 0x80000000) ; } ; return 1 ; } /* sds_3byte_read */ static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->read_block ++ ; psds->read_count = 0 ; if (psds->read_block * psds->samplesperblock > psds->frames) { memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ; return 1 ; } ; if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ; if (psds->read_data [0] != 0xF0) { printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ; } ; checksum = psds->read_data [1] ; if (checksum != 0x7E) { printf ("Error 1 : %02X\n", checksum & 0xFF) ; } for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->read_data [k] ; checksum &= 0x7F ; if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2]) { psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ; } ; ucptr = psds->read_data + 5 ; for (k = 0 ; k < 120 ; k += 4) { sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) + (ucptr [k + 3] << 4) ; psds->read_samples [k / 4] = (int) (sample - 0x80000000) ; } ; return 1 ; } /* sds_4byte_read */ static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = iptr [k] >> 16 ; total += count ; len -= readcount ; } ; return total ; } /* sds_read_s */ static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int total ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; total = sds_read (psf, psds, ptr, len) ; return total ; } /* sds_read_i */ static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; float normfact ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; if (psf->norm_float == SF_TRUE) normfact = 1.0 / 0x80000000 ; else normfact = 1.0 / (1 << psds->bitwidth) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* sds_read_f */ static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; double normfact ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; if (psf->norm_double == SF_TRUE) normfact = 1.0 / 0x80000000 ; else normfact = 1.0 / (1 << psds->bitwidth) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = sds_read (psf, psds, iptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * iptr [k] ; total += count ; len -= readcount ; } ; return total ; } /* sds_read_d */ static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len) { int count, total = 0 ; while (total < len) { if (psds->read_block * psds->samplesperblock >= psds->frames) { memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ; return total ; } ; if (psds->read_count >= psds->samplesperblock) psds->reader (psf, psds) ; count = (psds->samplesperblock - psds->read_count) ; count = (len - total > count) ? count : len - total ; memcpy (&(ptr [total]), &(psds->read_samples [psds->read_count]), count * sizeof (int)) ; total += count ; psds->read_count += count ; } ; return total ; } /* sds_read */ /*============================================================================== */ static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start) { SDS_PRIVATE *psds ; sf_count_t file_offset ; int newblock, newsample ; if ((psds = psf->fdata) == NULL) { psf->error = SFE_INTERNAL ; return SF_SEEK_ERROR ; } ; if (psf->datalength < 0 || psf->dataoffset < 0) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; if (seek_from_start < 0 || seek_from_start > psf->sf.frames) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; if (mode == SFM_READ && psds->write_count > 0) psds->writer (psf, psds) ; newblock = seek_from_start / psds->samplesperblock ; newsample = seek_from_start % psds->samplesperblock ; switch (mode) { case SFM_READ : if (newblock > psds->total_blocks) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ; if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset) { psf->error = SFE_SEEK_FAILED ; return SF_SEEK_ERROR ; } ; psds->read_block = newblock ; psds->reader (psf, psds) ; psds->read_count = newsample ; break ; case SFM_WRITE : if (newblock > psds->total_blocks) { psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; } ; file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ; if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset) { psf->error = SFE_SEEK_FAILED ; return SF_SEEK_ERROR ; } ; psds->write_block = newblock ; psds->reader (psf, psds) ; psds->write_count = newsample ; break ; default : psf->error = SFE_BAD_SEEK ; return SF_SEEK_ERROR ; break ; } ; return seek_from_start ; } /* sds_seek */ /*============================================================================== */ static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->write_data [0] = 0xF0 ; psds->write_data [1] = 0x7E ; psds->write_data [2] = 0 ; /* Channel number */ psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ ucptr = psds->write_data + 5 ; for (k = 0 ; k < 120 ; k += 2) { sample = psds->write_samples [k / 2] ; sample += 0x80000000 ; ucptr [k] = (sample >> 25) & 0x7F ; ucptr [k + 1] = (sample >> 18) & 0x7F ; } ; checksum = psds->write_data [1] ; for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->write_data [k] ; checksum &= 0x7F ; psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; psds->write_count = 0 ; if (psds->write_block > psds->total_blocks) psds->total_blocks = psds->write_block ; psds->frames = psds->total_blocks * psds->samplesperblock ; return 1 ; } /* sds_2byte_write */ static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->write_data [0] = 0xF0 ; psds->write_data [1] = 0x7E ; psds->write_data [2] = 0 ; /* Channel number */ psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ ucptr = psds->write_data + 5 ; for (k = 0 ; k < 120 ; k += 3) { sample = psds->write_samples [k / 3] ; sample += 0x80000000 ; ucptr [k] = (sample >> 25) & 0x7F ; ucptr [k + 1] = (sample >> 18) & 0x7F ; ucptr [k + 2] = (sample >> 11) & 0x7F ; } ; checksum = psds->write_data [1] ; for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->write_data [k] ; checksum &= 0x7F ; psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; psds->write_count = 0 ; if (psds->write_block > psds->total_blocks) psds->total_blocks = psds->write_block ; psds->frames = psds->total_blocks * psds->samplesperblock ; return 1 ; } /* sds_3byte_write */ static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) { unsigned char *ucptr, checksum ; unsigned int sample ; int k ; psds->write_data [0] = 0xF0 ; psds->write_data [1] = 0x7E ; psds->write_data [2] = 0 ; /* Channel number */ psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */ ucptr = psds->write_data + 5 ; for (k = 0 ; k < 120 ; k += 4) { sample = psds->write_samples [k / 4] ; sample += 0x80000000 ; ucptr [k] = (sample >> 25) & 0x7F ; ucptr [k + 1] = (sample >> 18) & 0x7F ; ucptr [k + 2] = (sample >> 11) & 0x7F ; ucptr [k + 3] = (sample >> 4) & 0x7F ; } ; checksum = psds->write_data [1] ; for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++) checksum ^= psds->write_data [k] ; checksum &= 0x7F ; psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ; psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ; if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE) psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ; psds->write_block ++ ; psds->write_count = 0 ; if (psds->write_block > psds->total_blocks) psds->total_blocks = psds->write_block ; psds->frames = psds->total_blocks * psds->samplesperblock ; return 1 ; } /* sds_4byte_write */ static sf_count_t sds_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = ptr [total + k] << 16 ; count = sds_write (psf, psds, iptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* sds_write_s */ static sf_count_t sds_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int total ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; total = sds_write (psf, psds, ptr, len) ; return total ; } /* sds_write_i */ static sf_count_t sds_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; float normfact ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; if (psf->norm_float == SF_TRUE) normfact = 1.0 * 0x80000000 ; else normfact = 1.0 * (1 << psds->bitwidth) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = normfact * ptr [total + k] ; count = sds_write (psf, psds, iptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* sds_write_f */ static sf_count_t sds_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { SDS_PRIVATE *psds ; int *iptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; double normfact ; if (psf->fdata == NULL) return 0 ; psds = (SDS_PRIVATE*) psf->fdata ; if (psf->norm_double == SF_TRUE) normfact = 1.0 * 0x80000000 ; else normfact = 1.0 * (1 << psds->bitwidth) ; iptr = (int*) psf->buffer ; bufferlen = sizeof (psf->buffer) / sizeof (int) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : len ; for (k = 0 ; k < writecount ; k++) iptr [k] = normfact * ptr [total + k] ; count = sds_write (psf, psds, iptr, writecount) ; total += count ; len -= writecount ; } ; return total ; } /* sds_write_d */ static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len) { int count, total = 0 ; while (total < len) { count = psds->samplesperblock - psds->write_count ; if (count > len - total) count = len - total ; memcpy (&(psds->write_samples [psds->write_count]), &(ptr [total]), count * sizeof (int)) ; total += count ; psds->write_count += count ; if (psds->write_count >= psds->samplesperblock) psds->writer (psf, psds) ; } ; return total ; } /* sds_write */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: d5d26aa3-368c-4ca6-bb85-377e5a2578cc */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*----------------------------------------------------------------------------------------------- ** Generic functions for performing endian swapping on integer arrays. */ void endswap_short_array (short *ptr, int len) { #if 0 unsigned char *ucptr, temp ; ucptr = ((unsigned char *) ptr) + 2 * len ; while (len > 0) { len -- ; ucptr -= 2 ; temp = ucptr [0] ; ucptr [0] = ucptr [1] ; ucptr [1] = temp ; } ; #else short temp ; while (len > 0) { len -- ; temp = ptr [len] ; ptr [len] = ENDSWAP_SHORT (temp) ; } #endif } /* endswap_short_array */ void endswap_int_array (int *ptr, int len) { #if 0 unsigned char *ucptr, temp ; ucptr = ((unsigned char *) ptr) + 4 * len ; while (len > 0) { len -- ; ucptr -= 4 ; temp = ucptr [0] ; ucptr [0] = ucptr [3] ; ucptr [3] = temp ; temp = ucptr [1] ; ucptr [1] = ucptr [2] ; ucptr [2] = temp ; } ; #else int temp ; while (len > 0) { len -- ; temp = ptr [len] ; ptr [len] = ENDSWAP_INT (temp) ; } ; #endif } /* endswap_int_array */ /* This function assumes that sizeof (long) == 8, but works correctly even ** is sizeof (long) == 4. */ void endswap_long_array (long *ptr, int len) { unsigned char *ucptr, temp ; ucptr = (unsigned char *) ptr + 8 * len ; while (len > 0) { len -- ; ucptr -= 8 ; temp = ucptr [0] ; ucptr [0] = ucptr [7] ; ucptr [7] = temp ; temp = ucptr [1] ; ucptr [1] = ucptr [6] ; ucptr [6] = temp ; temp = ucptr [2] ; ucptr [2] = ucptr [5] ; ucptr [5] = temp ; temp = ucptr [3] ; ucptr [3] = ucptr [4] ; ucptr [4] = temp ; } ; } /* endswap_long_array */ /*======================================================================================== */ void endswap_short_copy (short *dest, short *src, int len) { #if 0 char *psrc, *pdest ; psrc = ((char *) src) + 2 * len ; pdest = ((char *) dest) + 2 * len ; while (len > 0) { len -- ; psrc -= 2 ; pdest -= 2 ; pdest [0] = psrc [1] ; pdest [1] = psrc [0] ; } ; #else while (len > 0) { len -- ; dest [len] = ENDSWAP_SHORT (src [len]) ; } ; #endif } /* endswap_short_copy */ void endswap_int_copy (int *dest, int *src, int len) { #if 0 char *psrc, *pdest ; psrc = ((char *) src) + 4 * len ; pdest = ((char *) dest) + 4 * len ; while (len > 0) { len -- ; psrc -= 4 ; pdest -= 4 ; pdest [0] = psrc [3] ; pdest [1] = psrc [2] ; pdest [2] = psrc [1] ; pdest [3] = psrc [0] ; } ; #else while (len > 0) { len -- ; dest [len] = ENDSWAP_INT (src [len]) ; } ; #endif } /* endswap_int_copy */ /* This function assumes that sizeof (long) == 8, but works correctly even ** is sizeof (long) == 4. */ void endswap_long_copy (long *dest, long *src, int len) { char *psrc, *pdest ; psrc = (char *) src + 8 * len ; pdest = (char *) dest + 8 * len ; while (len > 0) { len -- ; psrc -= 8 ; pdest -= 8 ; pdest [0] = psrc [7] ; pdest [1] = psrc [6] ; pdest [2] = psrc [5] ; pdest [3] = psrc [4] ; pdest [4] = psrc [3] ; pdest [5] = psrc [2] ; pdest [6] = psrc [1] ; pdest [7] = psrc [0] ; } ; } /* endswap_long_copy */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 4cf6cc94-da4e-4ef5-aa4c-03dc6cd16810 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #include #include /* * SHORT TERM ANALYSIS FILTERING SECTION */ /* 4.2.8 */ static void Decoding_of_the_coded_Log_Area_Ratios ( word * LARc, /* coded log area ratio [0..7] IN */ word * LARpp) /* out: decoded .. */ { register word temp1 /* , temp2 */; /* This procedure requires for efficient implementation * two tables. * * INVA[1..8] = integer( (32768 * 8) / real_A[1..8]) * MIC[1..8] = minimum value of the LARc[1..8] */ /* Compute the LARpp[1..8] */ /* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) { * * temp1 = GSM_ADD( *LARc, *MIC ) << 10; * temp2 = *B << 1; * temp1 = GSM_SUB( temp1, temp2 ); * * assert(*INVA != MIN_WORD); * * temp1 = GSM_MULT_R( *INVA, temp1 ); * *LARpp = GSM_ADD( temp1, temp1 ); * } */ #undef short_termSTEP #define short_termSTEP( B, MIC, INVA ) \ temp1 = GSM_ADD( *LARc++, MIC ) << 10; \ temp1 = GSM_SUB( temp1, B << 1 ); \ temp1 = GSM_MULT_R( INVA, temp1 ); \ *LARpp++ = GSM_ADD( temp1, temp1 ); short_termSTEP( 0, -32, 13107 ); short_termSTEP( 0, -32, 13107 ); short_termSTEP( 2048, -16, 13107 ); short_termSTEP( -2560, -16, 13107 ); short_termSTEP( 94, -8, 19223 ); short_termSTEP( -1792, -8, 17476 ); short_termSTEP( -341, -4, 31454 ); short_termSTEP( -1144, -4, 29708 ); /* NOTE: the addition of *MIC is used to restore * the sign of *LARc. */ } /* 4.2.9 */ /* Computation of the quantized reflection coefficients */ /* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8] */ /* * Within each frame of 160 analyzed speech samples the short term * analysis and synthesis filters operate with four different sets of * coefficients, derived from the previous set of decoded LARs(LARpp(j-1)) * and the actual set of decoded LARs (LARpp(j)) * * (Initial value: LARpp(j-1)[1..8] = 0.) */ static void Coefficients_0_12 ( register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) { *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 )); *LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j_1, 1)); } } static void Coefficients_13_26 ( register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 1), SASR_W( *LARpp_j, 1 )); } } static void Coefficients_27_39 ( register word * LARpp_j_1, register word * LARpp_j, register word * LARp) { register int i; for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) { *LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 )); *LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j, 1 )); } } static void Coefficients_40_159 ( register word * LARpp_j, register word * LARp) { register int i; for (i = 1; i <= 8; i++, LARp++, LARpp_j++) *LARp = *LARpp_j; } /* 4.2.9.2 */ static void LARp_to_rp ( register word * LARp) /* [0..7] IN/OUT */ /* * The input of this procedure is the interpolated LARp[0..7] array. * The reflection coefficients, rp[i], are used in the analysis * filter and in the synthesis filter. */ { register int i; register word temp; for (i = 1; i <= 8; i++, LARp++) { /* temp = GSM_ABS( *LARp ); * * if (temp < 11059) temp <<= 1; * else if (temp < 20070) temp += 11059; * else temp = GSM_ADD( temp >> 2, 26112 ); * * *LARp = *LARp < 0 ? -temp : temp; */ if (*LARp < 0) { temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp); *LARp = - ((temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 : GSM_ADD( (word) (temp >> 2), (word) 26112 ))); } else { temp = *LARp; *LARp = (temp < 11059) ? temp << 1 : ((temp < 20070) ? temp + 11059 : GSM_ADD( (word) (temp >> 2), (word) 26112 )); } } } /* 4.2.10 */ static void Short_term_analysis_filtering ( struct gsm_state * S, register word * rp, /* [0..7] IN */ register int k_n, /* k_end - k_start */ register word * s /* [0..n-1] IN/OUT */ ) /* * This procedure computes the short term residual signal d[..] to be fed * to the RPE-LTP loop from the s[..] signal and from the local rp[..] * array (quantized reflection coefficients). As the call of this * procedure can be done in many ways (see the interpolation of the LAR * coefficient), it is assumed that the computation begins with index * k_start (for arrays d[..] and s[..]) and stops with index k_end * (k_start and k_end are defined in 4.2.9.1). This procedure also * needs to keep the array u[0..7] in memory for each call. */ { register word * u = S->u; register int i; register word di, zzz, ui, sav, rpi; for (; k_n--; s++) { di = sav = *s; for (i = 0; i < 8; i++) { /* YYY */ ui = u[i]; rpi = rp[i]; u[i] = sav; zzz = GSM_MULT_R(rpi, di); sav = GSM_ADD( ui, zzz); zzz = GSM_MULT_R(rpi, ui); di = GSM_ADD( di, zzz ); } *s = di; } } #if defined(USE_FLOAT_MUL) && defined(FAST) static void Fast_Short_term_analysis_filtering ( struct gsm_state * S, register word * rp, /* [0..7] IN */ register int k_n, /* k_end - k_start */ register word * s /* [0..n-1] IN/OUT */ ) { register word * u = S->u; register int i; float uf[8], rpf[8]; register float scalef = 3.0517578125e-5; register float sav, di, temp; for (i = 0; i < 8; ++i) { uf[i] = u[i]; rpf[i] = rp[i] * scalef; } for (; k_n--; s++) { sav = di = *s; for (i = 0; i < 8; ++i) { register float rpfi = rpf[i]; register float ufi = uf[i]; uf[i] = sav; temp = rpfi * di + ufi; di += rpfi * ufi; sav = temp; } *s = di; } for (i = 0; i < 8; ++i) u[i] = uf[i]; } #endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */ static void Short_term_synthesis_filtering ( struct gsm_state * S, register word * rrp, /* [0..7] IN */ register int k, /* k_end - k_start */ register word * wt, /* [0..k-1] IN */ register word * sr /* [0..k-1] OUT */ ) { register word * v = S->v; register int i; register word sri, tmp1, tmp2; while (k--) { sri = *wt++; for (i = 8; i--;) { /* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) ); */ tmp1 = rrp[i]; tmp2 = v[i]; tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD ? MAX_WORD : 0x0FFFF & (( (longword)tmp1 * (longword)tmp2 + 16384) >> 15)) ; sri = GSM_SUB( sri, tmp2 ); /* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) ); */ tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD ? MAX_WORD : 0x0FFFF & (( (longword)tmp1 * (longword)sri + 16384) >> 15)) ; v[i+1] = GSM_ADD( v[i], tmp1); } *sr++ = v[0] = sri; } } #if defined(FAST) && defined(USE_FLOAT_MUL) static void Fast_Short_term_synthesis_filtering ( struct gsm_state * S, register word * rrp, /* [0..7] IN */ register int k, /* k_end - k_start */ register word * wt, /* [0..k-1] IN */ register word * sr /* [0..k-1] OUT */ ) { register word * v = S->v; register int i; float va[9], rrpa[8]; register float scalef = 3.0517578125e-5, temp; for (i = 0; i < 8; ++i) { va[i] = v[i]; rrpa[i] = (float)rrp[i] * scalef; } while (k--) { register float sri = *wt++; for (i = 8; i--;) { sri -= rrpa[i] * va[i]; if (sri < -32768.) sri = -32768.; else if (sri > 32767.) sri = 32767.; temp = va[i] + rrpa[i] * sri; if (temp < -32768.) temp = -32768.; else if (temp > 32767.) temp = 32767.; va[i+1] = temp; } *sr++ = va[0] = sri; } for (i = 0; i < 9; ++i) v[i] = va[i]; } #endif /* defined(FAST) && defined(USE_FLOAT_MUL) */ void Gsm_Short_Term_Analysis_Filter ( struct gsm_state * S, word * LARc, /* coded log area ratio [0..7] IN */ word * s /* signal [0..159] IN/OUT */ ) { word * LARpp_j = S->LARpp[ S->j ]; word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ]; word LARp[8]; #undef FILTER #if defined(FAST) && defined(USE_FLOAT_MUL) # define FILTER (* (S->fast \ ? Fast_Short_term_analysis_filtering \ : Short_term_analysis_filtering )) #else # define FILTER Short_term_analysis_filtering #endif Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j ); Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER( S, LARp, 13, s); Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 14, s + 13); Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 13, s + 27); Coefficients_40_159( LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 120, s + 40); } void Gsm_Short_Term_Synthesis_Filter ( struct gsm_state * S, word * LARcr, /* received log area ratios [0..7] IN */ word * wt, /* received d [0..159] IN */ word * s /* signal s [0..159] OUT */ ) { word * LARpp_j = S->LARpp[ S->j ]; word * LARpp_j_1 = S->LARpp[ S->j ^=1 ]; word LARp[8]; #undef FILTER #if defined(FAST) && defined(USE_FLOAT_MUL) # define FILTER (* (S->fast \ ? Fast_Short_term_synthesis_filtering \ : Short_term_synthesis_filtering )) #else # define FILTER Short_term_synthesis_filtering #endif Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j ); Coefficients_0_12( LARpp_j_1, LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER( S, LARp, 13, wt, s ); Coefficients_13_26( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 14, wt + 13, s + 13 ); Coefficients_27_39( LARpp_j_1, LARpp_j, LARp); LARp_to_rp( LARp ); FILTER( S, LARp, 13, wt + 27, s + 27 ); Coefficients_40_159( LARpp_j, LARp ); LARp_to_rp( LARp ); FILTER(S, LARp, 120, wt + 40, s + 40); } /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 019ac7ba-c6dd-4540-abf0-8644b6c4a633 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #define SNDFILE_MAGICK 0x1234C0DE typedef struct { int error ; const char *str ; } ErrorStruct ; static ErrorStruct SndfileErrors [] = { /* Public error values and their associated strings. */ { SF_ERR_NO_ERROR , "No Error." }, { SF_ERR_UNRECOGNISED_FORMAT , "File opened for read. Format not recognised." }, { SF_ERR_SYSTEM , "System error." /* Often replaced. */ }, /* Private error values and their associated strings. */ { SFE_BAD_FILE , "File does not exist or is not a regular file (possibly a pipe?)." }, { SFE_BAD_FILE_READ , "File exists but no data could be read." }, { SFE_OPEN_FAILED , "Could not open file." }, { SFE_BAD_SNDFILE_PTR , "Not a valid SNDFILE* pointer." }, { SFE_BAD_SF_INFO_PTR , "NULL SF_INFO pointer passed to libsndfile." }, { SFE_BAD_SF_INCOMPLETE , "SF_PRIVATE struct incomplete and end of header parsing." }, { SFE_BAD_FILE_PTR , "Bad FILE pointer." }, { SFE_BAD_INT_PTR , "Internal error, Bad pointer." }, { SFE_BAD_STAT_SIZE , "Error : software was misconfigured at compile time (sizeof statbuf.st_size)." }, { SFE_MALLOC_FAILED , "Internal malloc () failed." }, { SFE_UNIMPLEMENTED , "File contains data in an unimplemented format." }, { SFE_BAD_READ_ALIGN , "Attempt to read a non-integer number of channels." }, { SFE_BAD_WRITE_ALIGN , "Attempt to write a non-integer number of channels." }, { SFE_UNKNOWN_FORMAT , "File contains data in an unknown format." }, { SFE_NOT_READMODE , "Read attempted on file currently open for write." }, { SFE_NOT_WRITEMODE , "Write attempted on file currently open for read." }, { SFE_BAD_MODE_RW , "This file format does not support read/write mode." }, { SFE_BAD_SF_INFO , "Internal error : SF_INFO struct incomplete." }, { SFE_BAD_OFFSET , "Error : supplied offset beyond end of file." }, { SFE_NO_EMBED_SUPPORT , "Error : embedding not supported for this file format." }, { SFE_NO_EMBEDDED_RDWR , "Error : cannot open embedded file read/write." }, { SFE_NO_PIPE_WRITE , "Error : this file format does not support pipe write." }, { SFE_BAD_RDWR_FORMAT , "Attempted to open read only format for RDWR." }, { SFE_INTERLEAVE_MODE , "Attempt to write to file with non-interleaved data." }, { SFE_INTERLEAVE_SEEK , "Bad karma in seek during interleave read operation." }, { SFE_INTERLEAVE_READ , "Bad karma in read during interleave read operation." }, { SFE_INTERNAL , "Unspecified internal error." }, { SFE_LOG_OVERRUN , "Log buffer has overrun. File probably broken." }, { SFE_BAD_CONTROL_CMD , "Bad command passed to function sf_command()." }, { SFE_BAD_ENDIAN , "Bad endian-ness. Try default endian-ness" }, { SFE_CHANNEL_COUNT , "Too many channels specified." }, { SFE_BAD_SEEK , "Internal psf_fseek() failed." }, { SFE_NOT_SEEKABLE , "Seek attempted on unseekable file type." }, { SFE_AMBIGUOUS_SEEK , "Error: combination of file open mode and seek command is ambiguous." }, { SFE_WRONG_SEEK , "Error: invalid seek parameters." }, { SFE_SEEK_FAILED , "Error: parameters OK, but psf_seek() failed." }, { SFE_BAD_OPEN_MODE , "Error: bad mode parameter for file open." }, { SFE_OPEN_PIPE_RDWR , "Error: attempt toopen a pipe in read/write mode." }, { SFE_RDWR_POSITION , "Error on RDWR position (cryptic)." }, { SFE_STR_NO_SUPPORT , "Error : File type does not support string data." }, { SFE_STR_MAX_DATA , "Error : Maximum string data storage reached." }, { SFE_STR_MAX_COUNT , "Error : Maximum string data count reached." }, { SFE_STR_BAD_TYPE , "Error : Bad string data type." }, { SFE_STR_NO_ADD_END , "Error : file type does not support strings added at end of file." }, { SFE_STR_BAD_STRING , "Error : bad string." }, { SFE_STR_WEIRD , "Error : Weird string error." }, { SFE_RDWR_BAD_HEADER , "Error : Cannot open file in read/write mode due to string data in header." }, { SFE_WAV_NO_RIFF , "Error in WAV file. No 'RIFF' chunk marker." }, { SFE_WAV_NO_WAVE , "Error in WAV file. No 'WAVE' chunk marker." }, { SFE_WAV_NO_FMT , "Error in WAV file. No 'fmt ' chunk marker." }, { SFE_WAV_FMT_SHORT , "Error in WAV file. Short 'fmt ' chunk." }, { SFE_WAV_FMT_TOO_BIG , "Error in WAV file. 'fmt ' chunk too large." }, { SFE_WAV_BAD_FACT , "Error in WAV file. 'fact' chunk out of place." }, { SFE_WAV_BAD_PEAK , "Error in WAV file. Bad 'PEAK' chunk." }, { SFE_WAV_PEAK_B4_FMT , "Error in WAV file. 'PEAK' chunk found before 'fmt ' chunk." }, { SFE_WAV_BAD_FORMAT , "Error in WAV file. Errors in 'fmt ' chunk." }, { SFE_WAV_BAD_BLOCKALIGN , "Error in WAV file. Block alignment in 'fmt ' chunk is incorrect." }, { SFE_WAV_NO_DATA , "Error in WAV file. No 'data' chunk marker." }, { SFE_WAV_UNKNOWN_CHUNK , "Error in WAV file. File contains an unknown chunk marker." }, { SFE_WAV_WVPK_DATA , "Error in WAV file. Data is in WAVPACK format." }, { SFE_WAV_ADPCM_NOT4BIT , "Error in ADPCM WAV file. Invalid bit width." }, { SFE_WAV_ADPCM_CHANNELS , "Error in ADPCM WAV file. Invalid number of channels." }, { SFE_WAV_GSM610_FORMAT , "Error in GSM610 WAV file. Invalid format chunk." }, { SFE_AIFF_NO_FORM , "Error in AIFF file, bad 'FORM' marker." }, { SFE_AIFF_AIFF_NO_FORM , "Error in AIFF file, 'AIFF' marker without 'FORM'." }, { SFE_AIFF_COMM_NO_FORM , "Error in AIFF file, 'COMM' marker without 'FORM'." }, { SFE_AIFF_SSND_NO_COMM , "Error in AIFF file, 'SSND' marker without 'COMM'." }, { SFE_AIFF_UNKNOWN_CHUNK , "Error in AIFF file, unknown chunk." }, { SFE_AIFF_COMM_CHUNK_SIZE, "Error in AIFF file, bad 'COMM' chunk size." }, { SFE_AIFF_BAD_COMM_CHUNK , "Error in AIFF file, bad 'COMM' chunk." }, { SFE_AIFF_PEAK_B4_COMM , "Error in AIFF file. 'PEAK' chunk found before 'COMM' chunk." }, { SFE_AIFF_BAD_PEAK , "Error in AIFF file. Bad 'PEAK' chunk." }, { SFE_AIFF_NO_SSND , "Error in AIFF file, bad 'SSND' chunk." }, { SFE_AIFF_NO_DATA , "Error in AIFF file, no sound data." }, { SFE_AIFF_RW_SSND_NOT_LAST, "Error in AIFF file, RDWR only possible if SSND chunk at end of file." }, { SFE_AU_UNKNOWN_FORMAT , "Error in AU file, unknown format." }, { SFE_AU_NO_DOTSND , "Error in AU file, missing '.snd' or 'dns.' marker." }, { SFE_AU_EMBED_BAD_LEN , "Embedded AU file with unknown length." }, { SFE_RAW_READ_BAD_SPEC , "Error while opening RAW file for read. Must specify format and channels.\n" "Possibly trying to open unsupported format." }, { SFE_RAW_BAD_BITWIDTH , "Error. RAW file bitwidth must be a multiple of 8." }, { SFE_RAW_BAD_FORMAT , "Error. Bad format field in SF_INFO struct when openning a RAW file for read." }, { SFE_PAF_NO_MARKER , "Error in PAF file, no marker." }, { SFE_PAF_VERSION , "Error in PAF file, bad version." }, { SFE_PAF_UNKNOWN_FORMAT , "Error in PAF file, unknown format." }, { SFE_PAF_SHORT_HEADER , "Error in PAF file. File shorter than minimal header." }, { SFE_SVX_NO_FORM , "Error in 8SVX / 16SV file, no 'FORM' marker." }, { SFE_SVX_NO_BODY , "Error in 8SVX / 16SV file, no 'BODY' marker." }, { SFE_SVX_NO_DATA , "Error in 8SVX / 16SV file, no sound data." }, { SFE_SVX_BAD_COMP , "Error in 8SVX / 16SV file, unsupported compression format." }, { SFE_SVX_BAD_NAME_LENGTH , "Error in 8SVX / 16SV file, NAME chunk too long." }, { SFE_NIST_BAD_HEADER , "Error in NIST file, bad header." }, { SFE_NIST_CRLF_CONVERISON, "Error : NIST file damaged by Windows CR -> CRLF conversion process." }, { SFE_NIST_BAD_ENCODING , "Error in NIST file, unsupported compression format." }, { SFE_VOC_NO_CREATIVE , "Error in VOC file, no 'Creative Voice File' marker." }, { SFE_VOC_BAD_FORMAT , "Error in VOC file, bad format." }, { SFE_VOC_BAD_VERSION , "Error in VOC file, bad version number." }, { SFE_VOC_BAD_MARKER , "Error in VOC file, bad marker in file." }, { SFE_VOC_BAD_SECTIONS , "Error in VOC file, incompatible VOC sections." }, { SFE_VOC_MULTI_SAMPLERATE, "Error in VOC file, more than one sample rate defined." }, { SFE_VOC_MULTI_SECTION , "Unimplemented VOC file feature, file contains multiple sound sections." }, { SFE_VOC_MULTI_PARAM , "Error in VOC file, file contains multiple bit or channel widths." }, { SFE_VOC_SECTION_COUNT , "Error in VOC file, too many sections." }, { SFE_VOC_NO_PIPE , "Error : not able to operate on VOC files over a pipe." }, { SFE_IRCAM_NO_MARKER , "Error in IRCAM file, bad IRCAM marker." }, { SFE_IRCAM_BAD_CHANNELS , "Error in IRCAM file, bad channel count." }, { SFE_IRCAM_UNKNOWN_FORMAT, "Error in IRCAM file, unknow encoding format." }, { SFE_W64_64_BIT , "Error in W64 file, file contains 64 bit offset." }, { SFE_W64_NO_RIFF , "Error in W64 file. No 'riff' chunk marker." }, { SFE_W64_NO_WAVE , "Error in W64 file. No 'wave' chunk marker." }, { SFE_W64_NO_FMT , "Error in W64 file. No 'fmt ' chunk marker." }, { SFE_W64_NO_DATA , "Error in W64 file. No 'data' chunk marker." }, { SFE_W64_FMT_SHORT , "Error in W64 file. Short 'fmt ' chunk." }, { SFE_W64_FMT_TOO_BIG , "Error in W64 file. 'fmt ' chunk too large." }, { SFE_W64_ADPCM_NOT4BIT , "Error in ADPCM W64 file. Invalid bit width." }, { SFE_W64_ADPCM_CHANNELS , "Error in ADPCM W64 file. Invalid number of channels." }, { SFE_W64_GSM610_FORMAT , "Error in GSM610 W64 file. Invalid format chunk." }, { SFE_MAT4_BAD_NAME , "Error in MAT4 file. No variable name." }, { SFE_MAT4_NO_SAMPLERATE , "Error in MAT4 file. No sample rate." }, { SFE_MAT4_ZERO_CHANNELS , "Error in MAT4 file. Channel count is zero." }, { SFE_MAT5_BAD_ENDIAN , "Error in MAT5 file. Not able to determine endian-ness." }, { SFE_MAT5_NO_BLOCK , "Error in MAT5 file. Bad block structure." }, { SFE_MAT5_SAMPLE_RATE , "Error in MAT5 file. Not able to determine sample rate." }, { SFE_MAT5_ZERO_CHANNELS , "Error in MAT5 file. Channel count is zero." }, { SFE_PVF_NO_PVF1 , "Error in PVF file. No PVF1 marker." }, { SFE_PVF_BAD_HEADER , "Error in PVF file. Bad header." }, { SFE_PVF_BAD_BITWIDTH , "Error in PVF file. Bad bit width." }, { SFE_XI_BAD_HEADER , "Error in XI file. Bad header." }, { SFE_XI_EXCESS_SAMPLES , "Error in XI file. Excess samples in file." }, { SFE_XI_NO_PIPE , "Error : not able to operate on XI files over a pipe." }, { SFE_HTK_NO_PIPE , "Error : not able to operate on HTK files over a pipe." }, { SFE_SDS_NOT_SDS , "Error : not an SDS file." }, { SFE_SDS_BAD_BIT_WIDTH , "Error : bad bit width for SDS file." }, { SFE_DWVW_BAD_BITWIDTH , "Error : Bad bit width for DWVW encoding. Must be 12, 16 or 24." }, { SFE_G72X_NOT_MONO , "Error : G72x encoding does not support more than 1 channel." }, { SFE_MAX_ERROR , "Maximum error number." }, { SFE_MAX_ERROR + 1 , NULL } } ; /*------------------------------------------------------------------------------ */ static int format_from_extension (const char *filename) ; static int guess_file_type (SF_PRIVATE *psf, const char *filename) ; static int validate_sfinfo (SF_INFO *sfinfo) ; static int validate_psf (SF_PRIVATE *psf) ; static void save_header_info (SF_PRIVATE *psf) ; static void copy_filename (SF_PRIVATE *psf, const char *path) ; static int psf_close (SF_PRIVATE *psf) ; static int psf_open_file (SF_PRIVATE *psf, int mode, SF_INFO *sfinfo) ; /*------------------------------------------------------------------------------ ** Private (static) variables. */ static int sf_errno = 0 ; static char sf_logbuffer [SF_BUFFER_LEN] = { 0 } ; static char sf_syserr [SF_SYSERR_LEN] = { 0 } ; /*------------------------------------------------------------------------------ */ #define VALIDATE_SNDFILE_AND_ASSIGN_PSF(a,b,c) \ { if (! (a)) \ { sf_errno = SFE_BAD_SNDFILE_PTR ; \ return 0 ; \ } ; \ (b) = (SF_PRIVATE*) (a) ; \ if (psf_filedes_valid (b) == 0) \ { (b)->error = SFE_BAD_FILE_PTR ; \ return 0 ; \ } ; \ if ((b)->Magick != SNDFILE_MAGICK) \ { (b)->error = SFE_BAD_SNDFILE_PTR ; \ return 0 ; \ } ; \ if (c) (b)->error = 0 ; \ } /*------------------------------------------------------------------------------ ** Public functions. */ SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) { SF_PRIVATE *psf ; int error = 0 ; if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) { sf_errno = SFE_MALLOC_FAILED ; return NULL ; } ; memset (psf, 0, sizeof (SF_PRIVATE)) ; psf_log_printf (psf, "File : %s\n", path) ; copy_filename (psf, path) ; if (strcmp (path, "-") == 0) error = psf_set_stdio (psf, mode) ; else error = psf_fopen (psf, path, mode) ; if (error == 0) error = psf_open_file (psf, mode, sfinfo) ; if (error) { sf_errno = error ; if (error == SFE_SYSTEM) LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; psf_close (psf) ; return NULL ; } ; memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; return (SNDFILE*) psf ; } /* sf_open */ SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) { SF_PRIVATE *psf ; int error ; if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL) { sf_errno = SFE_MALLOC_FAILED ; return NULL ; } ; psf_set_file (psf, fd) ; psf->is_pipe = psf_is_pipe (psf) ; psf->fileoffset = psf_ftell (psf) ; if (! close_desc) psf->do_not_close_descriptor = SF_TRUE ; error = psf_open_file (psf, mode, sfinfo) ; if (error) { sf_errno = error ; if (error == SFE_SYSTEM) LSF_SNPRINTF (sf_syserr, sizeof (sf_syserr), "%s", psf->syserr) ; LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; psf_close (psf) ; return NULL ; } ; memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; return (SNDFILE*) psf ; } /* sf_open_fd */ /*------------------------------------------------------------------------------ */ int sf_close (SNDFILE *sndfile) { SF_PRIVATE *psf ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; return psf_close (psf) ; } /* sf_close */ /*============================================================================== */ const char* sf_error_number (int errnum) { static const char *bad_errnum = "No error defined for this error number. This is a bug in libsndfile." ; int k ; if (errnum == SFE_MAX_ERROR) return SndfileErrors [0].str ; if (errnum < 0 || errnum > SFE_MAX_ERROR) { /* This really shouldn't happen in release versions. */ printf ("Not a valid error number (%d).\n", errnum) ; return bad_errnum ; } ; for (k = 0 ; SndfileErrors [k].str ; k++) if (errnum == SndfileErrors [k].error) return SndfileErrors [k].str ; return bad_errnum ; } /* sf_error_number */ const char* sf_strerror (SNDFILE *sndfile) { SF_PRIVATE *psf = NULL ; int errnum ; if (! sndfile) { errnum = sf_errno ; if (errnum == SFE_SYSTEM && sf_syserr [0]) return sf_syserr ; } else { psf = (SF_PRIVATE *) sndfile ; if (psf->Magick != SNDFILE_MAGICK) return "sf_strerror : Bad magic number." ; errnum = psf->error ; if (errnum == SFE_SYSTEM && psf->syserr [0]) return psf->syserr ; } ; return sf_error_number (errnum) ; } /* sf_strerror */ /*------------------------------------------------------------------------------ */ int sf_error (SNDFILE *sndfile) { SF_PRIVATE *psf ; if (! sndfile) { if (sf_error != 0) return 1 ; return 0 ; } ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; if (psf->error) return 1 ; return 0 ; } /* sf_error */ /*------------------------------------------------------------------------------ */ int sf_perror (SNDFILE *sndfile) { SF_PRIVATE *psf ; int errnum ; if (! sndfile) { errnum = sf_errno ; } else { VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; errnum = psf->error ; } ; fprintf (stderr, "%s\n", sf_error_number (errnum)) ; return SFE_NO_ERROR ; } /* sf_perror */ /*------------------------------------------------------------------------------ */ int sf_error_str (SNDFILE *sndfile, char *str, size_t maxlen) { SF_PRIVATE *psf ; int errnum ; if (! str) return SFE_INTERNAL ; if (! sndfile) errnum = sf_errno ; else { VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 0) ; errnum = psf->error ; } ; LSF_SNPRINTF (str, maxlen, "%s", sf_error_number (errnum)) ; return SFE_NO_ERROR ; } /* sf_error_str */ /*============================================================================== */ int sf_format_check (const SF_INFO *info) { int subformat, endian ; subformat = info->format & SF_FORMAT_SUBMASK ; endian = info->format & SF_FORMAT_ENDMASK ; /* This is the place where each file format can check if the suppiled ** SF_INFO struct is valid. ** Return 0 on failure, 1 ons success. */ if (info->channels < 1 || info->channels > 256) return 0 ; if (info->samplerate < 0) return 0 ; switch (info->format & SF_FORMAT_TYPEMASK) { case SF_FORMAT_WAV : case SF_FORMAT_WAVEX : /* WAV is strictly little endian. */ if (endian == SF_ENDIAN_BIG || endian == SF_ENDIAN_CPU) return 0 ; if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if ((subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) && info->channels <= 2) return 1 ; if (subformat == SF_FORMAT_GSM610 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; break ; case SF_FORMAT_AIFF : /* AIFF does allow both endian-nesses for PCM data.*/ if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; /* Other encodings. Check for endian-ness. */ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; if ((subformat == SF_FORMAT_DWVW_12 || subformat == SF_FORMAT_DWVW_16 || subformat == SF_FORMAT_DWVW_24) && info-> channels == 1) return 1 ; if (subformat == SF_FORMAT_GSM610 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_IMA_ADPCM && (info->channels == 1 || info->channels == 2)) return 1 ; break ; case SF_FORMAT_AU : if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; if (subformat == SF_FORMAT_G721_32 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_G723_24 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_G723_40 && info->channels == 1) return 1 ; break ; case SF_FORMAT_RAW : if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; if (subformat == SF_FORMAT_ALAW || subformat == SF_FORMAT_ULAW) return 1 ; if ((subformat == SF_FORMAT_DWVW_12 || subformat == SF_FORMAT_DWVW_16 || subformat == SF_FORMAT_DWVW_24) && info-> channels == 1) return 1 ; if (subformat == SF_FORMAT_GSM610 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_VOX_ADPCM && info->channels == 1) return 1 ; break ; case SF_FORMAT_PAF : if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; break ; case SF_FORMAT_SVX : /* SVX currently does not support more than one channel for write. ** Read will allow more than one channel but only allow one here. */ if (info->channels != 1) return 0 ; /* Always big endian. */ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if ((subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) && info->channels == 1) return 1 ; break ; case SF_FORMAT_NIST : if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; break ; case SF_FORMAT_IRCAM : if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW || subformat == SF_FORMAT_FLOAT) return 1 ; break ; case SF_FORMAT_VOC : /* VOC is strictly little endian. */ if (endian == SF_ENDIAN_BIG || endian == SF_ENDIAN_CPU) return 0 ; if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; break ; case SF_FORMAT_W64 : /* W64 is strictly little endian. */ if (endian == SF_ENDIAN_BIG || endian == SF_ENDIAN_CPU) return 0 ; if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16) return 1 ; if (subformat == SF_FORMAT_PCM_24 || subformat == SF_FORMAT_PCM_32) return 1 ; if ((subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) && info->channels <= 2) return 1 ; if (subformat == SF_FORMAT_GSM610 && info->channels == 1) return 1 ; if (subformat == SF_FORMAT_ULAW || subformat == SF_FORMAT_ALAW) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; break ; case SF_FORMAT_MAT4 : if (subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; break ; case SF_FORMAT_MAT5 : if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) return 1 ; if (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE) return 1 ; break ; case SF_FORMAT_PVF : if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_32) return 1 ; break ; case SF_FORMAT_XI : if (info->channels != 1) return 0 ; if (subformat == SF_FORMAT_DPCM_8 || subformat == SF_FORMAT_DPCM_16) return 1 ; break ; case SF_FORMAT_HTK : /* HTK is strictly big endian. */ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if (info->channels != 1) return 0 ; if (subformat == SF_FORMAT_PCM_16) return 1 ; break ; case SF_FORMAT_SDS : /* SDS is strictly big endian. */ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if (info->channels != 1) return 0 ; if (subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16 || subformat == SF_FORMAT_PCM_24) return 1 ; break ; case SF_FORMAT_AVR : /* SDS is strictly big endian. */ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if (info->channels < 1 || info->channels > 2) return 0 ; if (subformat == SF_FORMAT_PCM_U8 || subformat == SF_FORMAT_PCM_S8 || subformat == SF_FORMAT_PCM_16) return 1 ; break ; /*- case SF_FORMAT_SD2 : /+* SD2 is strictly big endian. *+/ if (endian == SF_ENDIAN_LITTLE || endian == SF_ENDIAN_CPU) return 0 ; if (subformat == SF_FORMAT_PCM_16) return 1 ; break ; -*/ default : break ; } ; return 0 ; } /* sf_format_check */ /*------------------------------------------------------------------------------ */ int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) { SF_PRIVATE *psf = NULL ; /* This set of commands do not need the sndfile parameter. */ switch (command) { case SFC_GET_LIB_VERSION : if (data == NULL) return (psf->error = SFE_BAD_CONTROL_CMD) ; if (ENABLE_EXPERIMENTAL_CODE) LSF_SNPRINTF (data, datasize, "%s-%s-exp", PACKAGE_NAME, PACKAGE_VERSION) ; else LSF_SNPRINTF (data, datasize, "%s-%s", PACKAGE_NAME, PACKAGE_VERSION) ; return 0 ; case SFC_GET_SIMPLE_FORMAT_COUNT : if (data == NULL || datasize != SIGNED_SIZEOF (int)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; *((int*) data) = psf_get_format_simple_count () ; return 0 ; case SFC_GET_SIMPLE_FORMAT : if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; return psf_get_format_simple (data) ; case SFC_GET_FORMAT_MAJOR_COUNT : if (data == NULL || datasize != SIGNED_SIZEOF (int)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; *((int*) data) = psf_get_format_major_count () ; return 0 ; case SFC_GET_FORMAT_MAJOR : if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; return psf_get_format_major (data) ; case SFC_GET_FORMAT_SUBTYPE_COUNT : if (data == NULL || datasize != SIGNED_SIZEOF (int)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; *((int*) data) = psf_get_format_subtype_count () ; return 0 ; case SFC_GET_FORMAT_SUBTYPE : if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; return psf_get_format_subtype (data) ; case SFC_GET_FORMAT_INFO : if (data == NULL || datasize != SIGNED_SIZEOF (SF_FORMAT_INFO)) return (sf_errno = SFE_BAD_CONTROL_CMD) ; return psf_get_format_info (data) ; } ; if (! sndfile && command == SFC_GET_LOG_INFO) { if (data == NULL) return (psf->error = SFE_BAD_CONTROL_CMD) ; LSF_SNPRINTF (data, datasize, "%s", sf_logbuffer) ; return 0 ; } ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; switch (command) { case SFC_SET_NORM_FLOAT : psf->norm_float = (datasize) ? SF_TRUE : SF_FALSE ; return psf->norm_float ; case SFC_SET_NORM_DOUBLE : psf->norm_double = (datasize) ? SF_TRUE : SF_FALSE ; return psf->norm_double ; case SFC_GET_NORM_FLOAT : return psf->norm_float ; case SFC_GET_NORM_DOUBLE : return psf->norm_double ; case SFC_SET_ADD_PEAK_CHUNK : { int format = psf->sf.format & SF_FORMAT_TYPEMASK ; /* Only WAV and AIFF support the PEAK chunk. */ if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX && format != SF_FORMAT_AIFF) return SF_FALSE ; format = psf->sf.format & SF_FORMAT_SUBMASK ; /* Only files containg the following data types support the PEAK chunk. */ if (format != SF_FORMAT_FLOAT && format != SF_FORMAT_DOUBLE) return SF_FALSE ; } ; /* Can only do this is in SFM_WRITE mode. */ if (psf->mode != SFM_WRITE) return SF_FALSE ; /* If data has already been written this must fail. */ if (psf->have_written) return psf->has_peak ; /* Everything seems OK, so set psf->has_peak and re-write header. */ psf->has_peak = (datasize) ? SF_TRUE : SF_FALSE ; if (psf->write_header) psf->write_header (psf, SF_TRUE) ; return psf->has_peak ; case SFC_GET_LOG_INFO : if (data == NULL) return (psf->error = SFE_BAD_CONTROL_CMD) ; LSF_SNPRINTF (data, datasize, "%s", psf->logbuffer) ; break ; case SFC_CALC_SIGNAL_MAX : if (data == NULL || datasize != sizeof (double)) return (psf->error = SFE_BAD_CONTROL_CMD) ; *((double*) data) = psf_calc_signal_max (psf, SF_FALSE) ; break ; case SFC_CALC_NORM_SIGNAL_MAX : if (data == NULL || datasize != sizeof (double)) return (psf->error = SFE_BAD_CONTROL_CMD) ; *((double*) data) = psf_calc_signal_max (psf, SF_TRUE) ; break ; case SFC_CALC_MAX_ALL_CHANNELS : if (data == NULL || datasize != SIGNED_SIZEOF (double) * psf->sf.channels) return (psf->error = SFE_BAD_CONTROL_CMD) ; return psf_calc_max_all_channels (psf, (double*) data, SF_FALSE) ; case SFC_CALC_NORM_MAX_ALL_CHANNELS : if (data == NULL || datasize != SIGNED_SIZEOF (double) * psf->sf.channels) return (psf->error = SFE_BAD_CONTROL_CMD) ; return psf_calc_max_all_channels (psf, (double*) data, SF_TRUE) ; case SFC_UPDATE_HEADER_NOW : if (psf->write_header) psf->write_header (psf, SF_TRUE) ; break ; case SFC_SET_UPDATE_HEADER_AUTO : psf->auto_header = datasize ? SF_TRUE : SF_FALSE ; return psf->auto_header ; break ; case SFC_SET_ADD_DITHER_ON_WRITE : case SFC_SET_ADD_DITHER_ON_READ : /* ** FIXME ! ** These are obsolete. Just return. ** Remove some time after version 1.0.8. */ break ; case SFC_SET_DITHER_ON_WRITE : if (data == NULL || datasize != SIGNED_SIZEOF (SF_DITHER_INFO)) return (psf->error = SFE_BAD_CONTROL_CMD) ; memcpy (&psf->write_dither, data, sizeof (psf->write_dither)) ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) dither_init (psf, SFM_WRITE) ; break ; case SFC_SET_DITHER_ON_READ : if (data == NULL || datasize != SIGNED_SIZEOF (SF_DITHER_INFO)) return (psf->error = SFE_BAD_CONTROL_CMD) ; memcpy (&psf->read_dither, data, sizeof (psf->read_dither)) ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) dither_init (psf, SFM_READ) ; break ; case SFC_FILE_TRUNCATE : if (psf->mode != SFM_WRITE && psf->mode != SFM_RDWR) return SF_TRUE ; if (datasize != sizeof (sf_count_t)) return SF_TRUE ; { sf_count_t position ; position = *((sf_count_t*) data) ; if (sf_seek (sndfile, position, SEEK_SET) != position) return SF_TRUE ; psf->sf.frames = position ; position = psf_fseek (psf, 0, SEEK_CUR) ; return psf_ftruncate (psf, position) ; } ; break ; case SFC_SET_RAW_START_OFFSET : if (data == NULL || datasize != sizeof (sf_count_t)) return (psf->error = SFE_BAD_CONTROL_CMD) ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) return (psf->error = SFE_BAD_CONTROL_CMD) ; psf->dataoffset = *((sf_count_t*) data) ; sf_seek (sndfile, 0, SEEK_CUR) ; break ; case SFC_GET_EMBED_FILE_INFO : if (data == NULL || datasize != sizeof (SF_EMBED_FILE_INFO)) return (psf->error = SFE_BAD_CONTROL_CMD) ; ((SF_EMBED_FILE_INFO*) data)->offset = psf->fileoffset ; ((SF_EMBED_FILE_INFO*) data)->length = psf->filelength ; break ; /* Lite remove start */ case SFC_TEST_IEEE_FLOAT_REPLACE : psf->ieee_replace = (datasize) ? SF_TRUE : SF_FALSE ; if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_FLOAT) float32_init (psf) ; else if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_DOUBLE) double64_init (psf) ; else return (psf->error = SFE_BAD_CONTROL_CMD) ; break ; /* Lite remove end */ case SFC_SET_CLIPPING : psf->add_clipping = (datasize) ? SF_TRUE : SF_FALSE ; return psf->add_clipping ; case SFC_GET_CLIPPING : return psf->add_clipping ; default : /* Must be a file specific command. Pass it on. */ if (psf->command) return psf->command (psf, command, data, datasize) ; psf_log_printf (psf, "*** sf_command : cmd = 0x%X\n", command) ; return (psf->error = SFE_BAD_CONTROL_CMD) ; } ; return 0 ; } /* sf_command */ /*------------------------------------------------------------------------------ */ sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t offset, int whence) { SF_PRIVATE *psf ; sf_count_t seek_from_start = 0, retval ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (! psf->sf.seekable) { psf->error = SFE_NOT_SEEKABLE ; return ((sf_count_t) -1) ; } ; /* If the whence parameter has a mode ORed in, check to see that ** it makes sense. */ if (((whence & SFM_MASK) == SFM_WRITE && psf->mode == SFM_READ) || ((whence & SFM_MASK) == SFM_WRITE && psf->mode == SFM_WRITE)) { psf->error = SFE_WRONG_SEEK ; return ((sf_count_t) -1) ; } ; /* Convert all SEEK_CUR and SEEK_END into seek_from_start to be ** used with SEEK_SET. */ switch (whence) { /* The SEEK_SET behaviour is independant of mode. */ case SEEK_SET : case SEEK_SET | SFM_READ : case SEEK_SET | SFM_WRITE : case SEEK_SET | SFM_RDWR : seek_from_start = offset ; break ; /* The SEEK_CUR is a little more tricky. */ case SEEK_CUR : if (offset == 0) { if (psf->mode == SFM_READ) return psf->read_current ; if (psf->mode == SFM_WRITE) return psf->write_current ; } ; if (psf->mode == SFM_READ) seek_from_start = psf->read_current + offset ; else if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) seek_from_start = psf->write_current + offset ; else psf->error = SFE_AMBIGUOUS_SEEK ; break ; case SEEK_CUR | SFM_READ : if (offset == 0) return psf->read_current ; seek_from_start = psf->read_current + offset ; break ; case SEEK_CUR | SFM_WRITE : if (offset == 0) return psf->write_current ; seek_from_start = psf->write_current + offset ; break ; /* The SEEK_END */ case SEEK_END : case SEEK_END | SFM_READ : case SEEK_END | SFM_WRITE : seek_from_start = psf->sf.frames + offset ; break ; default : psf->error = SFE_BAD_SEEK ; break ; } ; if (psf->error) return ((sf_count_t) -1) ; if (seek_from_start < 0 || seek_from_start > psf->sf.frames) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (psf->seek) { int new_mode = (whence & SFM_MASK) ? (whence & SFM_MASK) : psf->mode ; retval = psf->seek (psf, new_mode, seek_from_start) ; switch (new_mode) { case SFM_READ : psf->read_current = retval ; break ; case SFM_WRITE : psf->write_current = retval ; break ; case SFM_RDWR : psf->read_current = retval ; psf->write_current = retval ; new_mode = SFM_READ ; break ; } ; psf->last_op = new_mode ; return retval ; } ; psf->error = SFE_AMBIGUOUS_SEEK ; return ((sf_count_t) -1) ; } /* sf_seek */ /*------------------------------------------------------------------------------ */ const char* sf_get_string (SNDFILE *sndfile, int str_type) { SF_PRIVATE *psf ; if ((psf = (SF_PRIVATE*) sndfile) == NULL) return NULL ; if (psf->Magick != SNDFILE_MAGICK) return NULL ; return psf_get_string (psf, str_type) ; } /* sf_get_string */ int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) { SF_PRIVATE *psf ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; return psf_store_string (psf, str_type, str) ; } /* sf_get_string */ /*============================================================================== */ sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) { SF_PRIVATE *psf ; sf_count_t count ; int bytewidth, blockwidth ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; bytewidth = (psf->bytewidth > 0) ? psf->bytewidth : 1 ; blockwidth = (psf->blockwidth > 0) ? psf->blockwidth : 1 ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (bytes < 0 || psf->read_current >= psf->datalength) { psf_memset (ptr, 0, bytes) ; return 0 ; } ; if (bytes % (psf->sf.channels * bytewidth)) { psf->error = SFE_BAD_READ_ALIGN ; return 0 ; } ; count = psf_fread (ptr, 1, bytes, psf) ; if (count < bytes) psf_memset (((char*) ptr) + count, 0, bytes - count) ; psf->read_current += count / blockwidth ; psf->last_op = SFM_READ ; return count ; } /* sf_read_raw */ /*------------------------------------------------------------------------------ */ sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_READ_ALIGN ; return 0 ; } ; if (len <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, len * sizeof (short)) ; return 0 ; /* End of file. */ } ; if (! psf->read_short || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_short (psf, ptr, len) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = len - count ; psf_memset (ptr + count, 0, extra * sizeof (short)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count ; } /* sf_read_short */ sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (frames <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (short)) ; return 0 ; /* End of file. */ } ; if (! psf->read_short || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_short (psf, ptr, frames * psf->sf.channels) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = frames * psf->sf.channels - count ; psf_memset (ptr + count, 0, extra * sizeof (short)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count / psf->sf.channels ; } /* sf_readf_short */ /*------------------------------------------------------------------------------ */ sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_READ_ALIGN ; return 0 ; } ; if (len <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, len * sizeof (int)) ; return 0 ; } ; if (! psf->read_int || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_int (psf, ptr, len) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = len - count ; psf_memset (ptr + count, 0, extra * sizeof (int)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count ; } /* sf_read_int */ sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (frames <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (int)) ; return 0 ; } ; if (! psf->read_int || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_int (psf, ptr, frames * psf->sf.channels) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = frames * psf->sf.channels - count ; psf_memset (ptr + count, 0, extra * sizeof (int)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count / psf->sf.channels ; } /* sf_readf_int */ /*------------------------------------------------------------------------------ */ sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_READ_ALIGN ; return 0 ; } ; if (len <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, len * sizeof (float)) ; return 0 ; } ; if (! psf->read_float || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_float (psf, ptr, len) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = len - count ; psf_memset (ptr + count, 0, extra * sizeof (float)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count ; } /* sf_read_float */ sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (frames <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (float)) ; return 0 ; } ; if (! psf->read_float || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_float (psf, ptr, frames * psf->sf.channels) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = frames * psf->sf.channels - count ; psf_memset (ptr + count, 0, extra * sizeof (float)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count / psf->sf.channels ; } /* sf_readf_float */ /*------------------------------------------------------------------------------ */ sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_READ_ALIGN ; return 0 ; } ; if (len <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, len * sizeof (double)) ; return 0 ; } ; if (! psf->read_double || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_double (psf, ptr, len) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = len - count ; psf_memset (ptr + count, 0, extra * sizeof (double)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count ; } /* sf_read_double */ sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count, extra ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_WRITE) { psf->error = SFE_NOT_READMODE ; return 0 ; } ; if (frames <= 0 || psf->read_current >= psf->sf.frames) { psf_memset (ptr, 0, frames * psf->sf.channels * sizeof (double)) ; return 0 ; } ; if (! psf->read_double || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_READ) if (psf->seek (psf, SFM_READ, psf->read_current) < 0) return 0 ; count = psf->read_double (psf, ptr, frames * psf->sf.channels) ; if (psf->read_current + count / psf->sf.channels > psf->sf.frames) { count = (psf->sf.frames - psf->read_current) * psf->sf.channels ; extra = frames * psf->sf.channels - count ; psf_memset (ptr + count, 0, extra * sizeof (double)) ; psf->read_current = psf->sf.frames ; } ; psf->read_current += count / psf->sf.channels ; psf->last_op = SFM_READ ; if (psf->read_current > psf->sf.frames) { count = psf->sf.channels * (psf->read_current - psf->sf.frames) ; psf->read_current = psf->sf.frames ; } ; return count / psf->sf.channels ; } /* sf_readf_double */ /*------------------------------------------------------------------------------ */ sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count ; int bytewidth, blockwidth ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; bytewidth = (psf->bytewidth > 0) ? psf->bytewidth : 1 ; blockwidth = (psf->blockwidth > 0) ? psf->blockwidth : 1 ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (len % (psf->sf.channels * bytewidth)) { psf->error = SFE_BAD_WRITE_ALIGN ; return 0 ; } ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf_fwrite (ptr, 1, len, psf) ; psf->write_current += count / blockwidth ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; psf->last_op = SFM_WRITE ; return count ; } /* sf_write_raw */ /*------------------------------------------------------------------------------ */ sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_WRITE_ALIGN ; return 0 ; } ; if (! psf->write_short || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_short (psf, ptr, len) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count ; } /* sf_write_short */ sf_count_t sf_writef_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (! psf->write_short || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_short (psf, ptr, frames * psf->sf.channels) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count / psf->sf.channels ; } /* sf_writef_short */ /*------------------------------------------------------------------------------ */ sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_WRITE_ALIGN ; return 0 ; } ; if (! psf->write_int || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_int (psf, ptr, len) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count ; } /* sf_write_int */ sf_count_t sf_writef_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (! psf->write_int || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_int (psf, ptr, frames * psf->sf.channels) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count / psf->sf.channels ; } /* sf_writef_int */ /*------------------------------------------------------------------------------ */ sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_WRITE_ALIGN ; return 0 ; } ; if (! psf->write_float || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_float (psf, ptr, len) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count ; } /* sf_write_float */ sf_count_t sf_writef_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (! psf->write_float || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_float (psf, ptr, frames * psf->sf.channels) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count / psf->sf.channels ; } /* sf_writef_float */ /*------------------------------------------------------------------------------ */ sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t len) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (len % psf->sf.channels) { psf->error = SFE_BAD_WRITE_ALIGN ; return 0 ; } ; if (! psf->write_double || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_double (psf, ptr, len) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count ; } /* sf_write_double */ sf_count_t sf_writef_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) { SF_PRIVATE *psf ; sf_count_t count ; VALIDATE_SNDFILE_AND_ASSIGN_PSF (sndfile, psf, 1) ; if (psf->mode == SFM_READ) { psf->error = SFE_NOT_WRITEMODE ; return 0 ; } ; if (! psf->write_double || psf->seek == NULL) { psf->error = SFE_UNIMPLEMENTED ; return 0 ; } ; if (psf->last_op != SFM_WRITE) if (psf->seek (psf, SFM_WRITE, psf->write_current) < 0) return 0 ; if (psf->have_written == SF_FALSE && psf->write_header != NULL) psf->write_header (psf, SF_FALSE) ; psf->have_written = SF_TRUE ; count = psf->write_double (psf, ptr, frames * psf->sf.channels) ; psf->write_current += count / psf->sf.channels ; psf->last_op = SFM_WRITE ; if (psf->auto_header) psf->write_header (psf, SF_TRUE) ; if (psf->write_current > psf->sf.frames) psf->sf.frames = psf->write_current ; return count / psf->sf.channels ; } /* sf_writef_double */ /*========================================================================= ** Private functions. */ static int format_from_extension (const char *filename) { char *cptr ; char buffer [16] ; if (filename == NULL) return 0 ; if ((cptr = strrchr (filename, '.')) == NULL) return 0 ; cptr ++ ; if (strlen (cptr) > sizeof (buffer) - 1) return 0 ; strncpy (buffer, cptr, sizeof (buffer)) ; buffer [sizeof (buffer) - 1] = 0 ; /* Convert everything in the buffer to lower case. */ cptr = buffer ; while (*cptr) { *cptr = tolower (*cptr) ; cptr ++ ; } ; cptr = buffer ; if (strcmp (cptr, "au") == 0) return SF_FORMAT_AU | SF_FORMAT_ULAW ; if (strcmp (cptr, "snd") == 0) return SF_FORMAT_AU | SF_FORMAT_ULAW ; if (strcmp (cptr, "vox") == 0) return SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM ; return 0 ; } /* format_from_extension */ static int guess_file_type (SF_PRIVATE *psf, const char *filename) { int buffer [3], format ; unsigned char cptr [0x40] ; if (psf_binheader_readf (psf, "b", &buffer, SIGNED_SIZEOF (buffer)) != SIGNED_SIZEOF (buffer)) { psf->error = SFE_BAD_FILE_READ ; return 0 ; } ; if (buffer [0] == MAKE_MARKER ('R', 'I', 'F', 'F') && buffer [2] == MAKE_MARKER ('W', 'A', 'V', 'E')) return SF_FORMAT_WAV ; if (buffer [0] == MAKE_MARKER ('F', 'O', 'R', 'M')) { if (buffer [2] == MAKE_MARKER ('A', 'I', 'F', 'F') || buffer [2] == MAKE_MARKER ('A', 'I', 'F', 'C')) return SF_FORMAT_AIFF ; if (buffer [2] == MAKE_MARKER ('8', 'S', 'V', 'X') || buffer [2] == MAKE_MARKER ('1', '6', 'S', 'V')) return SF_FORMAT_SVX ; return 0 ; } ; if (buffer [0] == MAKE_MARKER ('.', 's', 'n', 'd') || buffer [0] == MAKE_MARKER ('d', 'n', 's', '.')) return SF_FORMAT_AU ; if ((buffer [0] == MAKE_MARKER ('f', 'a', 'p', ' ') || buffer [0] == MAKE_MARKER (' ', 'p', 'a', 'f'))) return SF_FORMAT_PAF ; if (buffer [0] == MAKE_MARKER ('N', 'I', 'S', 'T')) return SF_FORMAT_NIST ; if (buffer [0] == MAKE_MARKER ('C', 'r', 'e', 'a') && buffer [1] == MAKE_MARKER ('t', 'i', 'v', 'e')) return SF_FORMAT_VOC ; if ((buffer [0] & MAKE_MARKER (0xFF, 0xFF, 0xF8, 0xFF)) == MAKE_MARKER (0x64, 0xA3, 0x00, 0x00) || (buffer [0] & MAKE_MARKER (0xFF, 0xF8, 0xFF, 0xFF)) == MAKE_MARKER (0x00, 0x00, 0xA3, 0x64)) return SF_FORMAT_IRCAM ; if (buffer [0] == MAKE_MARKER ('r', 'i', 'f', 'f')) return SF_FORMAT_W64 ; if (buffer [0] == MAKE_MARKER (0, 0, 0x03, 0xE8) && buffer [1] == MAKE_MARKER (0, 0, 0, 1) && buffer [2] == MAKE_MARKER (0, 0, 0, 1)) return SF_FORMAT_MAT4 ; if (buffer [0] == MAKE_MARKER (0, 0, 0, 0) && buffer [1] == MAKE_MARKER (1, 0, 0, 0) && buffer [2] == MAKE_MARKER (1, 0, 0, 0)) return SF_FORMAT_MAT4 ; if (buffer [0] == MAKE_MARKER ('M', 'A', 'T', 'L') && buffer [1] == MAKE_MARKER ('A', 'B', ' ', '5')) return SF_FORMAT_MAT5 ; if (buffer [0] == MAKE_MARKER ('P', 'V', 'F', '1')) return SF_FORMAT_PVF ; if (buffer [0] == MAKE_MARKER ('E', 'x', 't', 'e') && buffer [1] == MAKE_MARKER ('n', 'd', 'e', 'd') && buffer [2] == MAKE_MARKER (' ', 'I', 'n', 's')) return SF_FORMAT_XI ; if (ENABLE_EXPERIMENTAL_CODE && buffer [0] == MAKE_MARKER ('O', 'g', 'g', 'S')) return SF_FORMAT_OGG ; if (buffer [0] == MAKE_MARKER ('A', 'L', 'a', 'w') && buffer [1] == MAKE_MARKER ('S', 'o', 'u', 'n') && buffer [2] == MAKE_MARKER ('d', 'F', 'i', 'l')) return SF_FORMAT_WVE ; if (buffer [0] == MAKE_MARKER ('D', 'i', 'a', 'm') && buffer [1] == MAKE_MARKER ('o', 'n', 'd', 'W') && buffer [2] == MAKE_MARKER ('a', 'r', 'e', ' ')) return SF_FORMAT_DWD ; if (buffer [0] == MAKE_MARKER ('L', 'M', '8', '9') || buffer [0] == MAKE_MARKER ('5', '3', 0, 0)) return SF_FORMAT_TXW ; if ((buffer [0] & MAKE_MARKER (0xFF, 0xFF, 0x80, 0xFF)) == MAKE_MARKER (0xF0, 0x7E, 0, 0x01)) return SF_FORMAT_SDS ; if (buffer [0] == MAKE_MARKER ('C', 'A', 'T', ' ') && buffer [2] == MAKE_MARKER ('R', 'E', 'X', '2')) return SF_FORMAT_REX2 ; if (buffer [0] == MAKE_MARKER (0x30, 0x26, 0xB2, 0x75) && buffer [1] == MAKE_MARKER (0x8E, 0x66, 0xCF, 0x11)) return 0 /*-SF_FORMAT_WMA-*/ ; /* HMM (Hidden Markov Model) Tool Kit. */ if (2 * BEI2H_INT (buffer [0]) + 12 == psf->filelength && buffer [2] == MAKE_MARKER (0, 2, 0, 0)) return SF_FORMAT_HTK ; if (buffer [0] == MAKE_MARKER ('f', 'L', 'a', 'C')) return 0 /*-SF_FORMAT_FLAC-*/ ; /* Turtle Beach SMP 16-bit */ if (buffer [0] == MAKE_MARKER ('S', 'O', 'U', 'N') && buffer [1] == MAKE_MARKER ('D', ' ', 'S', 'A')) return 0 ; if (buffer [0] == MAKE_MARKER ('S', 'Y', '8', '0') || buffer [0] == MAKE_MARKER ('S', 'Y', '8', '5')) return 0 ; if (buffer [0] == MAKE_MARKER ('a', 'j', 'k', 'g')) return 0 /*-SF_FORMAT_SHN-*/ ; if (buffer [0] == MAKE_MARKER ('2', 'B', 'I', 'T')) return SF_FORMAT_AVR ; if (OS_IS_MACOSX && (format = macos_guess_file_type (psf, filename)) != 0) return format ; /* Detect wacky MacOS header stuff. This might be "Sound Designer II". */ memcpy (cptr , buffer, sizeof (buffer)) ; if (cptr [0] == 0 && cptr [1] > 0 && psf->sf.seekable) { psf_binheader_readf (psf, "pb", 0, &cptr, SIGNED_SIZEOF (cptr)) ; if (cptr [1] < (sizeof (cptr) - 3) && cptr [cptr [1] + 2] == 0 && strlen (((char*) cptr) + 2) == cptr [1]) { psf_log_printf (psf, "Weird MacOS Header.\n") ; psf_binheader_readf (psf, "em", &buffer) ; if (buffer [0] == MAKE_MARKER (0, 'S', 'd', '2')) return SF_FORMAT_SD2 ; } ; } ; /* This must be the last one. */ if ((format = format_from_extension (filename)) != 0) return format ; /* Default to header-less RAW PCM file type. */ return SF_FORMAT_RAW ; } /* guess_file_type */ static int validate_sfinfo (SF_INFO *sfinfo) { if (sfinfo->samplerate < 1) return 0 ; if (sfinfo->frames < 0) return 0 ; if (sfinfo->channels < 1) return 0 ; if ((sfinfo->format & SF_FORMAT_TYPEMASK) == 0) return 0 ; if ((sfinfo->format & SF_FORMAT_SUBMASK) == 0) return 0 ; if (sfinfo->sections < 1) return 0 ; return 1 ; } /* validate_sfinfo */ static int validate_psf (SF_PRIVATE *psf) { if (psf->datalength < 0) { psf_log_printf (psf, "Invalid SF_PRIVATE field : datalength == %D.\n", psf->datalength) ; return 0 ; } ; if (psf->dataoffset < 0) { psf_log_printf (psf, "Invalid SF_PRIVATE field : dataoffset == %D.\n", psf->dataoffset) ; return 0 ; } ; if (psf->blockwidth && psf->blockwidth != psf->sf.channels * psf->bytewidth) { psf_log_printf (psf, "Invalid SF_PRIVATE field : channels * bytewidth == %d.\n", psf->sf.channels * psf->bytewidth) ; return 0 ; } ; return 1 ; } /* validate_psf */ static void save_header_info (SF_PRIVATE *psf) { LSF_SNPRINTF (sf_logbuffer, sizeof (sf_logbuffer), "%s", psf->logbuffer) ; } /* save_header_info */ static void copy_filename (SF_PRIVATE *psf, const char *path) { const char *cptr ; if ((cptr = strrchr (path, '/')) || (cptr = strrchr (path, '\\'))) cptr ++ ; else cptr = path ; memset (psf->filename, 0, SF_FILENAME_LEN) ; LSF_SNPRINTF (psf->filename, sizeof (psf->filename), "%s", cptr) ; } /* copy_filename */ /*============================================================================== */ static int psf_close (SF_PRIVATE *psf) { int error ; if (psf->close) error = psf->close (psf) ; psf_fclose (psf) ; if (psf->fdata) free (psf->fdata) ; if (psf->interleave) free (psf->interleave) ; if (psf->dither) free (psf->dither) ; if (psf->pchunk) free (psf->pchunk) ; if (psf->format_desc) { memset (psf->format_desc, 0, strlen (psf->format_desc)) ; free (psf->format_desc) ; } ; memset (psf, 0, sizeof (SF_PRIVATE)) ; free (psf) ; return 0 ; } /* psf_close */ static int psf_open_file (SF_PRIVATE *psf, int mode, SF_INFO *sfinfo) { int error, format ; if (mode != SFM_READ && mode != SFM_WRITE && mode != SFM_RDWR) return SFE_BAD_OPEN_MODE ; if (sfinfo == NULL) return SFE_BAD_SF_INFO_PTR ; if (mode == SFM_READ) { if ((sfinfo->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_RAW) { if (sf_format_check (sfinfo) == 0) return SFE_RAW_BAD_FORMAT ; } else memset (sfinfo, 0, sizeof (SF_INFO)) ; } ; sf_errno = error = 0 ; sf_logbuffer [0] = 0 ; memcpy (&(psf->sf), sfinfo, sizeof (SF_INFO)) ; psf->Magick = SNDFILE_MAGICK ; psf->norm_float = SF_TRUE ; psf->norm_double = SF_TRUE ; psf->mode = mode ; psf->dataoffset = -1 ; psf->datalength = -1 ; psf->read_current = -1 ; psf->write_current = -1 ; psf->auto_header = SF_FALSE ; psf->rwf_endian = SF_ENDIAN_LITTLE ; psf->seek = psf_default_seek ; psf->sf.sections = 1 ; psf->is_pipe = psf_is_pipe (psf) ; if (psf->is_pipe) { psf->sf.seekable = SF_FALSE ; psf->filelength = SF_COUNT_MAX ; } else { psf->sf.seekable = SF_TRUE ; /* File is open, so get the length. */ psf->filelength = psf_get_filelen (psf) ; } ; if (psf->fileoffset > 0) { switch (psf->mode) { case SFM_READ : if (psf->filelength < 44) { psf_log_printf (psf, "Short filelength: %D (fileoffset: %D)\n", psf->filelength, psf->fileoffset) ; return SFE_BAD_OFFSET ; } ; break ; case SFM_WRITE : psf->fileoffset = 0 ; psf_fseek (psf, 0, SEEK_END) ; psf->fileoffset = psf_ftell (psf) ; break ; case SFM_RDWR : return SFE_NO_EMBEDDED_RDWR ; } ; psf_log_printf (psf, "Embedded file offset : %D\n", psf->fileoffset) ; } ; if (psf->filelength == SF_COUNT_MAX) psf_log_printf (psf, "Length : unknown\n") ; else psf_log_printf (psf, "Length : %D\n", psf->filelength) ; if (mode == SFM_WRITE || (mode == SFM_RDWR && psf->filelength == 0)) { /* If the file is being opened for write or RDWR and the file is currently ** empty, then the SF_INFO struct must contain valid data. */ if (sf_format_check (&(psf->sf)) == 0) return SFE_BAD_OPEN_FORMAT ; } else if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW) { /* If type RAW has not been specified then need to figure out file type. */ psf->sf.format = guess_file_type (psf, psf->filename) ; } ; /* Prevent unnecessary seeks */ psf->last_op = psf->mode ; /* Set bytewidth if known. */ switch (psf->sf.format & SF_FORMAT_SUBMASK) { case SF_FORMAT_PCM_S8 : case SF_FORMAT_PCM_U8 : case SF_FORMAT_ULAW : case SF_FORMAT_ALAW : case SF_FORMAT_DPCM_8 : psf->bytewidth = 1 ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_DPCM_16 : psf->bytewidth = 2 ; break ; case SF_FORMAT_PCM_24 : psf->bytewidth = 3 ; break ; case SF_FORMAT_PCM_32 : case SF_FORMAT_FLOAT : psf->bytewidth = 4 ; break ; case SF_FORMAT_DOUBLE : psf->bytewidth = 8 ; break ; } ; /* Call the initialisation function for the relevant file type. */ switch (psf->sf.format & SF_FORMAT_TYPEMASK) { case SF_FORMAT_WAV : case SF_FORMAT_WAVEX : error = wav_open (psf) ; break ; case SF_FORMAT_AIFF : error = aiff_open (psf) ; break ; case SF_FORMAT_AU : error = au_open (psf) ; break ; case SF_FORMAT_AU | SF_FORMAT_ULAW : error = au_nh_open (psf) ; break ; case SF_FORMAT_RAW : error = raw_open (psf) ; break ; case SF_FORMAT_W64 : error = w64_open (psf) ; break ; /* Lite remove start */ case SF_FORMAT_PAF : error = paf_open (psf) ; break ; case SF_FORMAT_SVX : error = svx_open (psf) ; break ; case SF_FORMAT_NIST : error = nist_open (psf) ; break ; case SF_FORMAT_IRCAM : error = ircam_open (psf) ; break ; case SF_FORMAT_VOC : error = voc_open (psf) ; break ; case SF_FORMAT_SDS : error = sds_open (psf) ; break ; case SF_FORMAT_OGG : error = ogg_open (psf) ; break ; case SF_FORMAT_TXW : error = txw_open (psf) ; break ; case SF_FORMAT_WVE : error = wve_open (psf) ; break ; case SF_FORMAT_DWD : error = dwd_open (psf) ; break ; case SF_FORMAT_MAT4 : error = mat4_open (psf) ; break ; case SF_FORMAT_MAT5 : error = mat5_open (psf) ; break ; case SF_FORMAT_PVF : error = pvf_open (psf) ; break ; case SF_FORMAT_XI : error = xi_open (psf) ; break ; case SF_FORMAT_HTK : error = htk_open (psf) ; break ; case SF_FORMAT_SD2 : error = sd2_open (psf) ; break ; case SF_FORMAT_REX2 : error = rx2_open (psf) ; break ; case SF_FORMAT_AVR : error = avr_open (psf) ; break ; /* Lite remove end */ default : error = SFE_UNKNOWN_FORMAT ; } ; if (error) return error ; /* For now, check whether embedding is supported. */ format = psf->sf.format & SF_FORMAT_TYPEMASK ; if (psf->fileoffset > 0 && (format != SF_FORMAT_WAV) && (format != SF_FORMAT_WAVEX) && (format != SF_FORMAT_AIFF) && (format != SF_FORMAT_AU) ) return SFE_NO_EMBED_SUPPORT ; if (psf->fileoffset > 0) psf_log_printf (psf, "Embedded file length : %D\n", psf->filelength) ; if (mode == SFM_RDWR && sf_format_check (&(psf->sf)) == 0) return SFE_BAD_RDWR_FORMAT ; if (validate_sfinfo (&(psf->sf)) == 0) { psf_log_SF_INFO (psf) ; save_header_info (psf) ; return SFE_BAD_SF_INFO ; } ; if (validate_psf (psf) == 0) { save_header_info (psf) ; return SFE_INTERNAL ; } ; psf->read_current = 0 ; psf->write_current = (psf->mode == SFM_RDWR) ? psf->sf.frames : 0 ; memcpy (sfinfo, &(psf->sf), sizeof (SF_INFO)) ; return 0 ; } /* psf_open_file */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: cd4f9e91-a8ec-4154-9bf6-fe4b8c69a615 */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #define STRINGS_DEBUG 0 #if STRINGS_DEBUG static void hexdump (void *data, int len) ; #endif int psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) { static char lsf_name [] = PACKAGE "-" VERSION ; static char bracket_name [] = " (" PACKAGE "-" VERSION ")" ; int k, str_len, len_remaining, str_flags ; if (str == NULL) return SFE_STR_BAD_STRING ; str_len = strlen (str) ; /* A few extra checks for write mode. */ if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->str_flags & SF_STR_ALLOW_START) == 0) return SFE_STR_NO_SUPPORT ; if ((psf->str_flags & SF_STR_ALLOW_END) == 0) return SFE_STR_NO_SUPPORT ; /* Only allow zero length strings for software. */ if (str_type != SF_STR_SOFTWARE && str_len == 0) return SFE_STR_BAD_STRING ; } ; /* Determine flags */ str_flags = SF_STR_LOCATE_START ; if (psf->have_written) { if ((psf->str_flags & SF_STR_ALLOW_END) == 0) return SFE_STR_NO_ADD_END ; str_flags = SF_STR_LOCATE_END ; } ; /* Find next free slot in table. */ for (k = 0 ; k < SF_MAX_STRINGS ; k++) if (psf->strings [k].type == 0) break ; /* More sanity checking. */ if (k >= SF_MAX_STRINGS) return SFE_STR_MAX_COUNT ; if (k == 0 && psf->str_end != NULL) { psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ; return SFE_STR_WEIRD ; } ; if (k != 0 && psf->str_end == NULL) { psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ; return SFE_STR_WEIRD ; } ; /* Special case for the first string. */ if (k == 0) psf->str_end = psf->str_storage ; #if STRINGS_DEBUG psf_log_printf (psf, "str_storage : %X\n", (int) psf->str_storage) ; psf_log_printf (psf, "str_end : %X\n", (int) psf->str_end) ; psf_log_printf (psf, "sizeof (storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ; #endif len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ; if (len_remaining < str_len + 2) return SFE_STR_MAX_DATA ; switch (str_type) { case SF_STR_SOFTWARE : /* In write mode, want to append libsndfile-version to string. */ if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->strings [k].type = str_type ; psf->strings [k].str = psf->str_end ; psf->strings [k].flags = str_flags ; memcpy (psf->str_end, str, str_len + 1) ; psf->str_end += str_len ; /* ** If the supplied string does not already contain a ** libsndfile-X.Y.Z component, then add it. */ if (strstr (str, PACKAGE) == NULL && len_remaining > (int) (strlen (bracket_name) + str_len + 2)) { if (strlen (str) == 0) strncat (psf->str_end, lsf_name, len_remaining) ; else strncat (psf->str_end, bracket_name, len_remaining) ; psf->str_end += strlen (psf->str_end) ; } ; /* Plus one to catch string terminator. */ psf->str_end += 1 ; break ; } ; /* Fall though if not write mode. */ case SF_STR_TITLE : case SF_STR_COPYRIGHT : case SF_STR_ARTIST : case SF_STR_COMMENT : case SF_STR_DATE : psf->strings [k].type = str_type ; psf->strings [k].str = psf->str_end ; psf->strings [k].flags = str_flags ; /* Plus one to catch string terminator. */ memcpy (psf->str_end, str, str_len + 1) ; psf->str_end += str_len + 1 ; break ; default : return SFE_STR_BAD_TYPE ; } ; psf->str_flags |= (psf->have_written) ? SF_STR_LOCATE_END : SF_STR_LOCATE_START ; #if STRINGS_DEBUG hexdump (psf->str_storage, 300) ; #endif return 0 ; } /* psf_store_string */ const char* psf_get_string (SF_PRIVATE *psf, int str_type) { int k ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) if (str_type == psf->strings [k].type) return psf->strings [k].str ; return NULL ; } /* psf_get_string */ #if STRINGS_DEBUG #include static void hexdump (void *data, int len) { unsigned char *ptr ; int k ; ptr = data ; puts ("---------------------------------------------------------") ; while (len >= 16) { for (k = 0 ; k < 16 ; k++) printf ("%02X ", ptr [k] & 0xFF) ; printf (" ") ; for (k = 0 ; k < 16 ; k++) printf ("%c", isprint (ptr [k]) ? ptr [k] : '.') ; puts ("") ; ptr += 16 ; len -= 16 ; } ; } /* hexdump */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 04393aa1-9389-46fe-baf2-58a7bd544fd6 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M')) #define SVX8_MARKER (MAKE_MARKER ('8', 'S', 'V', 'X')) #define SV16_MARKER (MAKE_MARKER ('1', '6', 'S', 'V')) #define VHDR_MARKER (MAKE_MARKER ('V', 'H', 'D', 'R')) #define BODY_MARKER (MAKE_MARKER ('B', 'O', 'D', 'Y')) #define ATAK_MARKER (MAKE_MARKER ('A', 'T', 'A', 'K')) #define RLSE_MARKER (MAKE_MARKER ('R', 'L', 'S', 'E')) #define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' ')) #define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E')) #define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H')) #define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O')) #define CHAN_MARKER (MAKE_MARKER ('C', 'H', 'A', 'N')) /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ typedef struct { unsigned int oneShotHiSamples, repeatHiSamples, samplesPerHiCycle ; unsigned short samplesPerSec ; unsigned char octave, compression ; unsigned int volume ; } VHDR_CHUNK ; enum { svxHAVE_FORM = 0x01, HAVE_SVX = 0x02, HAVE_VHDR = 0x04, HAVE_BODY = 0x08 } ; /*------------------------------------------------------------------------------ * Private static functions. */ static int svx_close (SF_PRIVATE *psf) ; static int svx_write_header (SF_PRIVATE *psf, int calc_length) ; static int svx_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int svx_open (SF_PRIVATE *psf) { int error, subformat ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = svx_read_header (psf))) return error ; psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */ psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (psf->blockwidth) psf->sf.frames = psf->datalength / psf->blockwidth ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SVX) return SFE_BAD_OPEN_FORMAT ; psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ; if (psf->endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)) return SFE_BAD_ENDIAN ; psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */ error = svx_write_header (psf, SF_FALSE) ; if (error) return error ; psf->write_header = svx_write_header ; } ; psf->close = svx_close ; if ((error = pcm_init (psf))) return error ; return 0 ; } /* svx_open */ /*------------------------------------------------------------------------------ */ static int svx_read_header (SF_PRIVATE *psf) { VHDR_CHUNK vhdr ; unsigned int FORMsize, vhdrsize, dword, marker ; int filetype = 0, parsestage = 0, done = 0 ; int bytecount = 0, channels ; psf_binheader_readf (psf, "p", 0) ; /* Set default number of channels. */ psf->sf.channels = 1 ; psf->sf.format = SF_FORMAT_SVX ; while (! done) { psf_binheader_readf (psf, "m", &marker) ; switch (marker) { case FORM_MARKER : if (parsestage) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &FORMsize) ; if (FORMsize != psf->filelength - 2 * sizeof (dword)) { dword = psf->filelength - 2 * sizeof (dword) ; psf_log_printf (psf, "FORM : %d (should be %d)\n", FORMsize, dword) ; FORMsize = dword ; } else psf_log_printf (psf, "FORM : %d\n", FORMsize) ; parsestage |= svxHAVE_FORM ; break ; case SVX8_MARKER : case SV16_MARKER : if (! (parsestage & svxHAVE_FORM)) return SFE_SVX_NO_FORM ; filetype = marker ; psf_log_printf (psf, " %M\n", marker) ; parsestage |= HAVE_SVX ; break ; case VHDR_MARKER : if (! (parsestage & (svxHAVE_FORM | HAVE_SVX))) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &vhdrsize) ; psf_log_printf (psf, " VHDR : %d\n", vhdrsize) ; psf_binheader_readf (psf, "E4442114", &(vhdr.oneShotHiSamples), &(vhdr.repeatHiSamples), &(vhdr.samplesPerHiCycle), &(vhdr.samplesPerSec), &(vhdr.octave), &(vhdr.compression), &(vhdr.volume)) ; psf_log_printf (psf, " OneShotHiSamples : %d\n", vhdr.oneShotHiSamples) ; psf_log_printf (psf, " RepeatHiSamples : %d\n", vhdr.repeatHiSamples) ; psf_log_printf (psf, " samplesPerHiCycle : %d\n", vhdr.samplesPerHiCycle) ; psf_log_printf (psf, " Sample Rate : %d\n", vhdr.samplesPerSec) ; psf_log_printf (psf, " Octave : %d\n", vhdr.octave) ; psf_log_printf (psf, " Compression : %d => ", vhdr.compression) ; switch (vhdr.compression) { case 0 : psf_log_printf (psf, "None.\n") ; break ; case 1 : psf_log_printf (psf, "Fibonacci delta\n") ; break ; case 2 : psf_log_printf (psf, "Exponential delta\n") ; break ; } ; psf_log_printf (psf, " Volume : %d\n", vhdr.volume) ; psf->sf.samplerate = vhdr.samplesPerSec ; if (filetype == SVX8_MARKER) { psf->sf.format |= SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; } else if (filetype == SV16_MARKER) { psf->sf.format |= SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; } ; parsestage |= HAVE_VHDR ; break ; case BODY_MARKER : if (! (parsestage & HAVE_VHDR)) return SFE_SVX_NO_BODY ; psf_binheader_readf (psf, "E4", &dword) ; psf->datalength = dword ; psf->dataoffset = psf_ftell (psf) ; if (psf->datalength > psf->filelength - psf->dataoffset) { psf_log_printf (psf, " BODY : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ; psf->datalength = psf->filelength - psf->dataoffset ; } else psf_log_printf (psf, " BODY : %D\n", psf->datalength) ; parsestage |= HAVE_BODY ; if (! psf->sf.seekable) break ; psf_fseek (psf, psf->datalength, SEEK_CUR) ; break ; case NAME_MARKER : if (! (parsestage & HAVE_SVX)) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; if (strlen (psf->filename) != dword) { if (dword > sizeof (psf->filename) - 1) return SFE_SVX_BAD_NAME_LENGTH ; psf_binheader_readf (psf, "b", psf->filename, dword) ; psf->filename [dword] = 0 ; } else psf_binheader_readf (psf, "j", dword) ; break ; case ANNO_MARKER : if (! (parsestage & HAVE_SVX)) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; case CHAN_MARKER : if (! (parsestage & HAVE_SVX)) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; bytecount += psf_binheader_readf (psf, "E4", &channels) ; psf_log_printf (psf, " Channels : %d => %d\n", channels) ; psf_binheader_readf (psf, "j", dword - bytecount) ; break ; case AUTH_MARKER : case c_MARKER : if (! (parsestage & HAVE_SVX)) return SFE_SVX_NO_FORM ; psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, " %M : %d\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; default : if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) { psf_binheader_readf (psf, "E4", &dword) ; psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; } ; if ((dword = psf_ftell (psf)) & 0x03) { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; psf_binheader_readf (psf, "j", -3) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; done = 1 ; } ; /* switch (marker) */ if (! psf->sf.seekable && (parsestage & HAVE_BODY)) break ; if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword)) break ; } ; /* while (1) */ if (vhdr.compression) return SFE_SVX_BAD_COMP ; if (psf->dataoffset <= 0) return SFE_SVX_NO_DATA ; return 0 ; } /* svx_read_header */ static int svx_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) svx_write_header (psf, SF_TRUE) ; return 0 ; } /* svx_close */ static int svx_write_header (SF_PRIVATE *psf, int calc_length) { static char annotation [] = "libsndfile by Erik de Castro Lopo\0\0\0" ; sf_count_t current ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* FORM marker and FORM size. */ psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ? psf->filelength * 0 : psf->filelength - 8) ; psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ; /* VHDR chunk. */ psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ; /* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */ psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ; /* VHDR : samplesPerSec, octave, compression */ psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ; /* VHDR : volume */ psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ; /* Filename and annotation strings. */ psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, ANNO_MARKER, annotation) ; /* BODY marker and size. */ psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ? psf->datalength * 0 : psf->datalength) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* svx_write_header */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: a80ab6fb-7d75-4d32-a6b0-0061a3f05d95 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ /* Most of these tables are inlined at their point of use. */ /* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP * CODER AND DECODER * * (Most of them inlined, so watch out.) */ #define GSM_TABLE_C /* Table 4.1 Quantization of the Log.-Area Ratios */ /* i 1 2 3 4 5 6 7 8 */ word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036}; word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144}; word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 }; word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 }; /* Table 4.2 Tabulation of 1/A[1..8] */ word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 }; /* Table 4.3a Decision level of the LTP gain quantizer */ /* bc 0 1 2 3 */ word gsm_DLB[4] = { 6554, 16384, 26214, 32767 }; /* Table 4.3b Quantization levels of the LTP gain quantizer */ /* bc 0 1 2 3 */ word gsm_QLB[4] = { 3277, 11469, 21299, 32767 }; /* Table 4.4 Coefficients of the weighting filter */ /* i 0 1 2 3 4 5 6 7 8 9 10 */ word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 }; /* Table 4.5 Normalized inverse mantissa used to compute xM/xmax */ /* i 0 1 2 3 4 5 6 7 */ word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 }; /* Table 4.6 Normalized direct mantissa used to compute xM/xmax */ /* i 0 1 2 3 4 5 6 7 */ word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 }; /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 8957c531-e6b0-4097-9202-da7ca42729ca */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /*=========================================================================== ** Yamaha TX16 Sampler Files. ** ** This header parser was written using information from the SoX source code ** and trial and error experimentation. The code here however is all original. */ #include #include #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int txw_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* txw_open */ #else /*------------------------------------------------------------------------------ ** Markers. */ #define TXW_DATA_OFFSET 32 #define TXW_LOOPED 0x49 #define TXW_NO_LOOP 0xC9 /*------------------------------------------------------------------------------ ** Private static functions. */ static int txw_read_header (SF_PRIVATE *psf) ; static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; /*------------------------------------------------------------------------------ ** Public functions. */ /* * ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha * ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec * http://www.t0.or.at/~mpakesch/tx16w/ * * from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith) * char filetype[6] "LM8953" * nulls[10], * dummy_aeg[6] * format 0x49 = looped, 0xC9 = non-looped * sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz * atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16, * depending on [5] but to heck with it * rpt_length[3] (these are for looped samples, attack and loop lengths) * unused[2] */ typedef struct { unsigned char format, srate, sr2, sr3 ; unsigned short srhash ; unsigned int attacklen, repeatlen ; } TXW_HEADER ; #define ERROR_666 666 int txw_open (SF_PRIVATE *psf) { int error ; if (psf->mode != SFM_READ) return SFE_UNIMPLEMENTED ; if ((error = txw_read_header (psf))) return error ; if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset) return SFE_BAD_SEEK ; psf->read_short = txw_read_s ; psf->read_int = txw_read_i ; psf->read_float = txw_read_f ; psf->read_double = txw_read_d ; psf->seek = txw_seek ; return 0 ; } /* txw_open */ /*------------------------------------------------------------------------------ */ static int txw_read_header (SF_PRIVATE *psf) { TXW_HEADER txwh ; char *strptr ; memset (&txwh, 0, sizeof (txwh)) ; memset (psf->buffer, 0, sizeof (psf->buffer)) ; psf_binheader_readf (psf, "pb", 0, psf->buffer, 16) ; if (memcmp (psf->buffer, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0) return ERROR_666 ; psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ; /* Jump 6 bytes (dummp_aeg), read format, read sample rate. */ psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ; /* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */ psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ; txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ; txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ; txwh.attacklen &= 0x1FFFF ; txwh.repeatlen &= 0x1FFFF ; switch (txwh.format) { case TXW_LOOPED : strptr = "looped" ; break ; case TXW_NO_LOOP : strptr = "non-looped" ; break ; default : psf_log_printf (psf, " Format : 0x%02x => ?????\n", txwh.format) ; return ERROR_666 ; } ; psf_log_printf (psf, " Format : 0x%02X => %s\n", txwh.format, strptr) ; strptr = NULL ; switch (txwh.srate) { case 1 : psf->sf.samplerate = 33333 ; break ; case 2 : psf->sf.samplerate = 50000 ; break ; case 3 : psf->sf.samplerate = 16667 ; break ; default : /* This is ugly and braindead. */ txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ; switch (txwh.srhash) { case ((0x6 << 8) | 0x52) : psf->sf.samplerate = 33333 ; break ; case ((0x10 << 8) | 0x52) : psf->sf.samplerate = 50000 ; break ; case ((0xF6 << 8) | 0x52) : psf->sf.samplerate = 166667 ; break ; default : strptr = " Sample Rate : Unknown : forcing to 33333\n" ; psf->sf.samplerate = 33333 ; break ; } ; } ; if (strptr) psf_log_printf (psf, strptr) ; else if (txwh.srhash) psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ; else psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ; if (txwh.format == TXW_LOOPED) { psf_log_printf (psf, " Attack Len : %d\n", txwh.attacklen) ; psf_log_printf (psf, " Repeat Len : %d\n", txwh.repeatlen) ; } ; psf->dataoffset = TXW_DATA_OFFSET ; psf->datalength = psf->filelength - TXW_DATA_OFFSET ; psf->sf.frames = 2 * psf->datalength / 3 ; if (psf->datalength % 3 == 1) psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n", (int) (psf->datalength % 3)) ; if (txwh.attacklen + txwh.repeatlen > psf->sf.frames) psf_log_printf (psf, "*** File has been truncated.\n") ; psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ; psf->sf.channels = 1 ; psf->sf.sections = 1 ; psf->sf.seekable = SF_TRUE ; return 0 ; } /* txw_read_header */ static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { unsigned char *ucptr ; short sample ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / 3 ; bufferlen -= (bufferlen & 1) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = psf_fread (psf->buffer, 3, readcount, psf) ; ucptr = (unsigned char *) psf->buffer ; for (k = 0 ; k < readcount ; k += 2) { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; ptr [total + k] = sample ; sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; ptr [total + k + 1] = sample ; ucptr += 3 ; } ; total += count ; len -= readcount ; } ; return total ; } /* txw_read_s */ static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { unsigned char *ucptr ; short sample ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / 3 ; bufferlen -= (bufferlen & 1) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = psf_fread (psf->buffer, 3, readcount, psf) ; ucptr = (unsigned char *) psf->buffer ; for (k = 0 ; k < readcount ; k += 2) { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; ptr [total + k] = sample << 16 ; sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; ptr [total + k + 1] = sample << 16 ; ucptr += 3 ; } ; total += count ; len -= readcount ; } ; return total ; } /* txw_read_i */ static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { unsigned char *ucptr ; short sample ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; float normfact ; if (psf->norm_float == SF_TRUE) normfact = 1.0 / 0x8000 ; else normfact = 1.0 / 0x10 ; bufferlen = sizeof (psf->buffer) / 3 ; bufferlen -= (bufferlen & 1) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = psf_fread (psf->buffer, 3, readcount, psf) ; ucptr = (unsigned char *) psf->buffer ; for (k = 0 ; k < readcount ; k += 2) { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; ptr [total + k] = normfact * sample ; sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; ptr [total + k + 1] = normfact * sample ; ucptr += 3 ; } ; total += count ; len -= readcount ; } ; return total ; } /* txw_read_f */ static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { unsigned char *ucptr ; short sample ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; double normfact ; if (psf->norm_double == SF_TRUE) normfact = 1.0 / 0x8000 ; else normfact = 1.0 / 0x10 ; bufferlen = sizeof (psf->buffer) / 3 ; bufferlen -= (bufferlen & 1) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : len ; count = psf_fread (psf->buffer, 3, readcount, psf) ; ucptr = (unsigned char *) psf->buffer ; for (k = 0 ; k < readcount ; k += 2) { sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ; ptr [total + k] = normfact * sample ; sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ; ptr [total + k + 1] = normfact * sample ; ucptr += 3 ; } ; total += count ; len -= readcount ; } ; return total ; } /* txw_read_d */ static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { if (psf && mode) return offset ; return 0 ; } /* txw_seek */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 4d0ba7af-b1c5-46b4-a900-7c6f59fd9a89 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ static sf_count_t ulaw_read_ulaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t ulaw_read_ulaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t ulaw_read_ulaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t ulaw_read_ulaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t ulaw_write_s2ulaw (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t ulaw_write_i2ulaw (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t ulaw_write_f2ulaw (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t ulaw_write_d2ulaw (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static void ulaw2s_array (unsigned char *buffer, unsigned int count, short *ptr) ; static void ulaw2i_array (unsigned char *buffer, unsigned int count, int *ptr) ; static void ulaw2f_array (unsigned char *buffer, unsigned int count, float *ptr, float normfact) ; static void ulaw2d_array (unsigned char *buffer, unsigned int count, double *ptr, double normfact) ; static void s2ulaw_array (short *buffer, unsigned int count, unsigned char *ptr) ; static void i2ulaw_array (int *buffer, unsigned int count, unsigned char *ptr) ; static void f2ulaw_array (float *buffer, unsigned int count, unsigned char *ptr, float normfact) ; static void d2ulaw_array (double *buffer, unsigned int count, unsigned char *ptr, double normfact) ; int ulaw_init (SF_PRIVATE *psf) { if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { psf->read_short = ulaw_read_ulaw2s ; psf->read_int = ulaw_read_ulaw2i ; psf->read_float = ulaw_read_ulaw2f ; psf->read_double = ulaw_read_ulaw2d ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { psf->write_short = ulaw_write_s2ulaw ; psf->write_int = ulaw_write_i2ulaw ; psf->write_float = ulaw_write_f2ulaw ; psf->write_double = ulaw_write_d2ulaw ; } ; psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels ; if (psf->filelength > psf->dataoffset) psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; else psf->datalength = 0 ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* ulaw_init */ static sf_count_t ulaw_read_ulaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; ulaw2s_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* ulaw_read_ulaw2s */ static sf_count_t ulaw_read_ulaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; ulaw2i_array ((unsigned char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* ulaw_read_ulaw2i */ static sf_count_t ulaw_read_ulaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; ulaw2f_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* ulaw_read_ulaw2f */ static sf_count_t ulaw_read_ulaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, 1, readcount, psf) ; ulaw2d_array ((unsigned char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; if (thisread < readcount) break ; len -= thisread ; } ; return total ; } /* ulaw_read_ulaw2d */ /*============================================================================================= */ static sf_count_t ulaw_write_s2ulaw (SF_PRIVATE *psf, short *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2ulaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer)) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* ulaw_write_s2ulaw */ static sf_count_t ulaw_write_i2ulaw (SF_PRIVATE *psf, int *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2ulaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer)) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* ulaw_write_i2ulaw */ static sf_count_t ulaw_write_f2ulaw (SF_PRIVATE *psf, float *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; float normfact ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; f2ulaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer), normfact) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* ulaw_write_f2ulaw */ static sf_count_t ulaw_write_d2ulaw (SF_PRIVATE *psf, double *ptr, sf_count_t len) { int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; double normfact ; normfact = (psf->norm_double) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; d2ulaw_array (ptr + total, writecount, (unsigned char*) (psf->buffer), normfact) ; thiswrite = psf_fwrite (psf->buffer, 1, writecount, psf) ; total += thiswrite ; if (thiswrite < writecount) break ; len -= thiswrite ; } ; return total ; } /* ulaw_write_d2ulaw */ /*============================================================================================= * Private static functions and data. */ static short ulaw_decode [128] = { -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, } ; static unsigned char ulaw_encode [8193] = { 0xFF, 0xFE, 0xFE, 0xFD, 0xFD, 0xFC, 0xFC, 0xFB, 0xFB, 0xFA, 0xFA, 0xF9, 0xF9, 0xF8, 0xF8, 0xF7, 0xF7, 0xF6, 0xF6, 0xF5, 0xF5, 0xF4, 0xF4, 0xF3, 0xF3, 0xF2, 0xF2, 0xF1, 0xF1, 0xF0, 0xF0, 0xEF, 0xEF, 0xEF, 0xEF, 0xEE, 0xEE, 0xEE, 0xEE, 0xED, 0xED, 0xED, 0xED, 0xEC, 0xEC, 0xEC, 0xEC, 0xEB, 0xEB, 0xEB, 0xEB, 0xEA, 0xEA, 0xEA, 0xEA, 0xE9, 0xE9, 0xE9, 0xE9, 0xE8, 0xE8, 0xE8, 0xE8, 0xE7, 0xE7, 0xE7, 0xE7, 0xE6, 0xE6, 0xE6, 0xE6, 0xE5, 0xE5, 0xE5, 0xE5, 0xE4, 0xE4, 0xE4, 0xE4, 0xE3, 0xE3, 0xE3, 0xE3, 0xE2, 0xE2, 0xE2, 0xE2, 0xE1, 0xE1, 0xE1, 0xE1, 0xE0, 0xE0, 0xE0, 0xE0, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDF, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDE, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDC, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDB, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xDA, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD9, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD7, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD5, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD4, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD3, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD2, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD1, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xD0, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCF, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCE, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCD, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCB, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xCA, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC9, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC8, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC5, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC4, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC2, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBF, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBE, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBD, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBC, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xBA, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB9, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB8, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB7, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB6, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB5, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB4, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB3, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB2, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB1, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xB0, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAF, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAD, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAC, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAB, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA9, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA8, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA5, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA4, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA3, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA2, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA1, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0xA0, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9F, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9E, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9D, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9C, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x9A, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x96, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8F, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8E, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8D, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8C, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x8A, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00 } ; static void ulaw2s_array (unsigned char *buffer, unsigned int count, short *ptr) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -1 * ulaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = ulaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* ulaw2s_array */ static void ulaw2i_array (unsigned char *buffer, unsigned int count, int *ptr) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -1 * ulaw_decode [buffer [count] & 0x7F] << 16 ; else ptr [count] = ulaw_decode [buffer [count] & 0x7F] << 16 ; } ; } /* ulaw2i_array */ static void ulaw2f_array (unsigned char *buffer, unsigned int count, float *ptr, float normfact) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -normfact * ulaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = normfact * ulaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* ulaw2f_array */ static void ulaw2d_array (unsigned char *buffer, unsigned int count, double *ptr, double normfact) { while (count) { count -- ; if (buffer [count] & 0x80) ptr [count] = -normfact * ulaw_decode [((int) buffer [count]) & 0x7F] ; else ptr [count] = normfact * ulaw_decode [((int) buffer [count]) & 0x7F] ; } ; } /* ulaw2d_array */ static void s2ulaw_array (short *ptr, unsigned int count, unsigned char *buffer) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = ulaw_encode [ptr [count] / 4] ; else buffer [count] = 0x7F & ulaw_encode [ptr [count] / -4] ; } ; } /* s2ulaw_array */ static void i2ulaw_array (int *ptr, unsigned int count, unsigned char *buffer) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = ulaw_encode [ptr [count] >> (16 + 2)] ; else buffer [count] = 0x7F & ulaw_encode [-ptr [count] >> (16 + 2)] ; } ; } /* i2ulaw_array */ static void f2ulaw_array (float *ptr, unsigned int count, unsigned char *buffer, float normfact) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = ulaw_encode [(lrintf (normfact * ptr [count])) / 4] ; else buffer [count] = 0x7F & ulaw_encode [(lrintf (normfact * ptr [count])) / -4] ; } ; } /* f2ulaw_array */ static void d2ulaw_array (double *ptr, unsigned int count, unsigned char *buffer, double normfact) { while (count) { count -- ; if (ptr [count] >= 0) buffer [count] = ulaw_encode [(lrint (normfact * ptr [count])) / 4] ; else buffer [count] = 0x7F & ulaw_encode [(lrint (normfact * ptr [count])) / -4] ; } ; } /* d2ulaw_array */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 655cc790-f058-45e8-89c9-86967cccc37e */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* RANT: ** The VOC file format is the most brain damaged format I have yet had to deal ** with. No one programmer could have bee stupid enough to put this together. ** Instead it looks like a series of manic, dyslexic assembly language programmers ** hacked it to fit their needs. ** Utterly woeful. */ #include #include #include /*------------------------------------------------------------------------------ * Typedefs for file chunks. */ #define VOC_MAX_SECTIONS 200 enum { VOC_TERMINATOR = 0, VOC_SOUND_DATA = 1, VOC_SOUND_CONTINUE = 2, VOC_SILENCE = 3, VOC_MARKER = 4, VOC_ASCII = 5, VOC_REPEAT = 6, VOC_END_REPEAT = 7, VOC_EXTENDED = 8, VOC_EXTENDED_II = 9 } ; typedef struct { int samples ; int offset ; /* Offset of zero => silence. */ } SND_DATA_BLOCKS ; typedef struct { unsigned int sections, section_types ; int samplerate, channels, bitwidth ; SND_DATA_BLOCKS blocks [VOC_MAX_SECTIONS] ; } VOC_DATA ; /*------------------------------------------------------------------------------ * Private static functions. */ static int voc_close (SF_PRIVATE *psf) ; static int voc_write_header (SF_PRIVATE *psf, int calc_length) ; static int voc_read_header (SF_PRIVATE *psf) ; static const char* voc_encoding2str (int encoding) ; #if 0 /* These functions would be required for files with more than one VOC_SOUND_DATA ** segment. Not sure whether to bother implementing this. */ static int voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) ; static int voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) ; static int voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) ; static int voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) ; static int voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) ; static int voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) ; static int voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) ; static int voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) ; static int voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) ; #endif /*------------------------------------------------------------------------------ ** Public function. */ int voc_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->is_pipe) return SFE_VOC_NO_PIPE ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = voc_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC) return SFE_BAD_OPEN_FORMAT ; psf->endian = SF_ENDIAN_LITTLE ; if ((error = voc_write_header (psf, SF_FALSE))) return error ; psf->write_header = voc_write_header ; } ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->close = voc_close ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : error = pcm_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; return error ; } /* voc_open */ /*------------------------------------------------------------------------------ */ static int voc_read_header (SF_PRIVATE *psf) { VOC_DATA *pvoc ; char creative [20] ; unsigned char block_type, rate_byte ; short version, checksum, encoding, dataoffset ; int offset ; /* Set position to start of file to begin reading header. */ offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ; if (creative [sizeof (creative) - 1] != 0x1A) return SFE_VOC_NO_CREATIVE ; /* Terminate the string. */ creative [sizeof (creative) - 1] = 0 ; if (strcmp ("Creative Voice File", creative)) return SFE_VOC_NO_CREATIVE ; psf_log_printf (psf, "%s\n", creative) ; offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ; psf->dataoffset = dataoffset ; psf_log_printf (psf, "dataoffset : %d\n" "version : 0x%X\n" "checksum : 0x%X\n", psf->dataoffset, version, checksum) ; if (version != 0x010A && version != 0x0114) return SFE_VOC_BAD_VERSION ; if (! (psf->fdata = malloc (sizeof (VOC_DATA)))) return SFE_MALLOC_FAILED ; pvoc = (VOC_DATA*) psf->fdata ; memset (pvoc, 0, sizeof (VOC_DATA)) ; /* Set the default encoding now. */ psf->sf.format = SF_FORMAT_VOC ; /* Major format */ encoding = SF_FORMAT_PCM_U8 ; /* Minor format */ psf->endian = SF_ENDIAN_LITTLE ; while (1) { offset += psf_binheader_readf (psf, "1", &block_type) ; switch (block_type) { case VOC_ASCII : { int size ; offset += psf_binheader_readf (psf, "e3", &size) ; psf_log_printf (psf, " ASCII : %d\n", size) ; offset += psf_binheader_readf (psf, "b", psf->header, size) ; psf->header [size] = 0 ; psf_log_printf (psf, " text : %s\n", psf->header) ; } ; continue ; case VOC_SOUND_DATA : case VOC_EXTENDED : case VOC_EXTENDED_II : break ; default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ; } ; break ; } ; if (block_type == VOC_SOUND_DATA) { unsigned char compression ; int size ; offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ; psf_log_printf (psf, " Sound Data : %d\n sr : %d => %dHz\n comp : %d\n", size, rate_byte, psf->sf.samplerate, compression) ; if (offset + size - 1 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } else if (offset + size - 1 < psf->filelength) { psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; psf->sf.channels = 1 ; psf->bytewidth = 1 ; psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; return 0 ; } ; if (block_type == VOC_EXTENDED) { unsigned char pack, stereo, compression ; unsigned short rate_short ; int size ; offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ; psf_log_printf (psf, " Extended : %d\n", size) ; if (size == 4) psf_log_printf (psf, " size : 4\n") ; else psf_log_printf (psf, " size : %d (should be 4)\n", size) ; psf_log_printf (psf, " pack : %d\n" " stereo : %s\n", pack, (stereo ? "yes" : "no")) ; if (stereo) { psf->sf.channels = 2 ; psf->sf.samplerate = 128000000 / (65536 - rate_short) ; } else { psf->sf.channels = 1 ; psf->sf.samplerate = 256000000 / (65536 - rate_short) ; } ; psf_log_printf (psf, " sr : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ; offset += psf_binheader_readf (psf, "1", &block_type) ; if (block_type != VOC_SOUND_DATA) { psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ; return SFE_VOC_BAD_FORMAT ; } ; offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; psf_log_printf (psf, " Sound Data : %d\n" " sr : %d\n" " comp : %d\n", size, rate_byte, compression) ; if (offset + size - 1 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } else if (offset + size - 1 < psf->filelength) { psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; psf->bytewidth = 1 ; psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; return 0 ; } if (block_type == VOC_EXTENDED_II) { unsigned char bitwidth, channels ; int size, fourbytes ; offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate, &bitwidth, &channels, &encoding, &fourbytes) ; if (size * 2 == psf->filelength - 39) { int temp_size = psf->filelength - 31 ; psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ; size = temp_size ; } else psf_log_printf (psf, " Extended II : %d\n", size) ; psf_log_printf (psf, " sample rate : %d\n" " bit width : %d\n" " channels : %d\n", psf->sf.samplerate, bitwidth, channels) ; if (bitwidth == 16 && encoding == 0) { encoding = 4 ; psf_log_printf (psf, " encoding : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ; } else psf_log_printf (psf, " encoding : %d => %s\n", encoding, voc_encoding2str (encoding)) ; psf_log_printf (psf, " fourbytes : %X\n", fourbytes) ; psf->sf.channels = channels ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; if (size + 31 == psf->filelength + 1) { /* Hack for reading files produced using ** sf_command (SFC_UPDATE_HEADER_NOW). */ psf_log_printf (psf, "Missing zero byte at end of file.\n") ; size = psf->filelength - 30 ; psf->dataend = 0 ; } else if (size + 31 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; size = psf->filelength - 31 ; } else if (size + 31 < psf->filelength) psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ; switch (encoding) { case 0 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; psf->bytewidth = 1 ; break ; case 4 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; case 6 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ; psf->bytewidth = 1 ; break ; case 7 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ; psf->bytewidth = 1 ; break ; default : /* Unknown */ return SFE_UNKNOWN_FORMAT ; break ; } ; } ; return 0 ; } /* voc_read_header */ /*==================================================================================== */ static int voc_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int rate_const, subformat ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* VOC marker and 0x1A byte. */ psf_binheader_writef (psf, "eb1", "Creative Voice File", 19, 0x1A) ; /* Data offset, version and other. */ psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ; /* Use same logic as SOX. ** If the file is mono 8 bit data, use VOC_SOUND_DATA. ** If the file is mono 16 bit data, use VOC_EXTENED. ** Otherwise use VOC_EXTENED_2. */ if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 1) { /* samplerate = 1000000 / (256 - rate_const) ; */ rate_const = 256 - 1000000 / psf->sf.samplerate ; /* First type marker, length, rate_const and compression */ psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; } else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2) { /* sample_rate = 128000000 / (65536 - rate_short) ; */ rate_const = 65536 - 128000000 / psf->sf.samplerate ; /* First write the VOC_EXTENDED section ** marker, length, rate_const and compression */ psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ; /* samplerate = 1000000 / (256 - rate_const) ; */ rate_const = 256 - 1000000 / psf->sf.samplerate ; /* Now write the VOC_SOUND_DATA section ** marker, length, rate_const and compression */ psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ; } else { int length ; if (psf->sf.channels < 1 || psf->sf.channels > 2) return SFE_CHANNEL_COUNT ; switch (subformat) { case SF_FORMAT_PCM_U8 : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; break ; case SF_FORMAT_PCM_16 : psf->bytewidth = 2 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */ psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ; break ; case SF_FORMAT_ALAW : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ; break ; case SF_FORMAT_ULAW : psf->bytewidth = 1 ; length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ; psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ; break ; default : return SFE_UNIMPLEMENTED ; } ; } ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* voc_write_header */ static int voc_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { /* Now we know for certain the length of the file we can re-write ** correct values for the FORM, 8SVX and BODY chunks. */ unsigned byte = VOC_TERMINATOR ; psf_fseek (psf, 0, SEEK_END) ; /* Write terminator */ psf_fwrite (&byte, 1, 1, psf) ; voc_write_header (psf, SF_TRUE) ; } ; return 0 ; } /* voc_close */ static const char* voc_encoding2str (int encoding) { switch (encoding) { case 0 : return "8 bit unsigned PCM" ; case 4 : return "16 bit signed PCM" ; case 6 : return "A-law" ; case 7 : return "u-law" ; default : break ; } return "*** Unknown ***" ; } /* voc_encoding2str */ /*==================================================================================== */ #if 0 static int voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) { psf->sf.frames = 0 ; if (pvoc->bitwidth == 8) { psf->read_short = voc_multi_read_uc2s ; psf->read_int = voc_multi_read_uc2i ; psf->read_float = voc_multi_read_uc2f ; psf->read_double = voc_multi_read_uc2d ; return 0 ; } ; if (pvoc->bitwidth == 16) { psf->read_short = voc_multi_read_les2s ; psf->read_int = voc_multi_read_les2i ; psf->read_float = voc_multi_read_les2f ; psf->read_double = voc_multi_read_les2d ; return 0 ; } ; psf_log_printf (psf, "Error : bitwith != 8 && bitwidth != 16.\n") ; return SFE_UNIMPLEMENTED ; } /* voc_multi_read_int */ /*------------------------------------------------------------------------------------ */ static int voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) { return 0 ; } /* voc_multi_read_uc2s */ static int voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) { return 0 ; } /* voc_multi_read_les2s */ static int voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) { return 0 ; } /* voc_multi_read_uc2i */ static int voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) { return 0 ; } /* voc_multi_read_les2i */ static int voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) { return 0 ; } /* voc_multi_read_uc2f */ static int voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) { return 0 ; } /* voc_multi_read_les2f */ static int voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) { return 0 ; } /* voc_multi_read_uc2d */ static int voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) { return 0 ; } /* voc_multi_read_les2d */ #endif /*------------------------------------------------------------------------------------ Creative Voice (VOC) file format -------------------------------- ~From: galt@dsd.es.com (byte numbers are hex!) HEADER (bytes 00-19) Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] - --------------------------------------------------------------- HEADER: ======= byte # Description ------ ------------------------------------------ 00-12 "Creative Voice File" 13 1A (eof to abort printing of file) 14-15 Offset of first datablock in .voc file (std 1A 00 in Intel Notation) 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) 18-19 1's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) - --------------------------------------------------------------- DATA BLOCK: =========== Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) NOTE: Terminator Block is an exception -- it has only the TYPE byte. TYPE Description Size (3-byte int) Info ---- ----------- ----------------- ----------------------- 00 Terminator (NONE) (NONE) 01 Sound data 2+length of data * 02 Sound continue length of data Voice Data 03 Silence 3 ** 04 Marker 2 Marker# (2 bytes) 05 ASCII length of string null terminated string 06 Repeat 2 Count# (2 bytes) 07 End repeat 0 (NONE) 08 Extended 4 *** *Sound Info Format: --------------------- 00 Sample Rate 01 Compression Type 02+ Voice Data **Silence Info Format: ---------------------------- 00-01 Length of silence - 1 02 Sample Rate ***Extended Info Format: --------------------- 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) Stereo: 65536 - (25600000/(2*sample_rate)) 02 Pack 03 Mode: 0 = mono 1 = stereo Marker# -- Driver keeps the most recent marker in a status byte Count# -- Number of repetitions + 1 Count# may be 1 to FFFE for 0 - FFFD repetitions or FFFF for endless repetitions Sample Rate -- SR byte = 256-(1000000/sample_rate) Length of silence -- in units of sampling cycle Compression Type -- of voice data 8-bits = 0 4-bits = 1 2.6-bits = 2 2-bits = 3 Multi DAC = 3+(# of channels) [interesting-- this isn't in the developer's manual] --------------------------------------------------------------------------------- Addendum submitted by Votis Kokavessis: After some experimenting with .VOC files I found out that there is a Data Block Type 9, which is not covered in the VOC.TXT file. Here is what I was able to discover about this block type: TYPE: 09 SIZE: 12 + length of data INFO: 12 (twelve) bytes INFO STRUCTURE: Bytes 0-1: (Word) Sample Rate (e.g. 44100) Bytes 2-3: zero (could be that bytes 0-3 are a DWord for Sample Rate) Byte 4: Sample Size in bits (e.g. 16) Byte 5: Number of channels (e.g. 1 for mono, 2 for stereo) Byte 6: Unknown (equal to 4 in all files I examined) Bytes 7-11: zero -------------------------------------------------------------------------------------*/ /*===================================================================================== **===================================================================================== **===================================================================================== **===================================================================================== */ /*------------------------------------------------------------------------ The following is taken from the Audio File Formats FAQ dated 2-Jan-1995 and submitted by Guido van Rossum . -------------------------------------------------------------------------- Creative Voice (VOC) file format -------------------------------- From: galt@dsd.es.com (byte numbers are hex!) HEADER (bytes 00-19) Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] - --------------------------------------------------------------- HEADER: ------- byte # Description ------ ------------------------------------------ 00-12 "Creative Voice File" 13 1A (eof to abort printing of file) 14-15 Offset of first datablock in .voc file (std 1A 00 in Intel Notation) 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) - --------------------------------------------------------------- DATA BLOCK: ----------- Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) NOTE: Terminator Block is an exception -- it has only the TYPE byte. TYPE Description Size (3-byte int) Info ---- ----------- ----------------- ----------------------- 00 Terminator (NONE) (NONE) 01 Sound data 2+length of data * 02 Sound continue length of data Voice Data 03 Silence 3 ** 04 Marker 2 Marker# (2 bytes) 05 ASCII length of string null terminated string 06 Repeat 2 Count# (2 bytes) 07 End repeat 0 (NONE) 08 Extended 4 *** *Sound Info Format: **Silence Info Format: --------------------- ---------------------------- 00 Sample Rate 00-01 Length of silence - 1 01 Compression Type 02 Sample Rate 02+ Voice Data ***Extended Info Format: --------------------- 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) Stereo: 65536 - (25600000/(2*sample_rate)) 02 Pack 03 Mode: 0 = mono 1 = stereo Marker# -- Driver keeps the most recent marker in a status byte Count# -- Number of repetitions + 1 Count# may be 1 to FFFE for 0 - FFFD repetitions or FFFF for endless repetitions Sample Rate -- SR byte = 256-(1000000/sample_rate) Length of silence -- in units of sampling cycle Compression Type -- of voice data 8-bits = 0 4-bits = 1 2.6-bits = 2 2-bits = 3 Multi DAC = 3+(# of channels) [interesting-- this isn't in the developer's manual] Detailed description of new data blocks (VOC files version 1.20 and above): (Source is fax from Barry Boone at Creative Labs, 405/742-6622) BLOCK 8 - digitized sound attribute extension, must preceed block 1. Used to define stereo, 8 bit audio BYTE bBlockID; // = 8 BYTE nBlockLen[3]; // 3 byte length WORD wTimeConstant; // time constant = same as block 1 BYTE bPackMethod; // same as in block 1 BYTE bVoiceMode; // 0-mono, 1-stereo Data is stored left, right BLOCK 9 - data block that supersedes blocks 1 and 8. Used for stereo, 16 bit. BYTE bBlockID; // = 9 BYTE nBlockLen[3]; // length 12 plus length of sound DWORD dwSamplesPerSec; // samples per second, not time const. BYTE bBitsPerSample; // e.g., 8 or 16 BYTE bChannels; // 1 for mono, 2 for stereo WORD wFormat; // see below BYTE reserved[4]; // pad to make block w/o data // have a size of 16 bytes Valid values of wFormat are: 0x0000 8-bit unsigned PCM 0x0001 Creative 8-bit to 4-bit ADPCM 0x0002 Creative 8-bit to 3-bit ADPCM 0x0003 Creative 8-bit to 2-bit ADPCM 0x0004 16-bit signed PCM 0x0006 CCITT a-Law 0x0007 CCITT u-Law 0x02000 Creative 16-bit to 4-bit ADPCM Data is stored left, right ------------------------------------------------------------------------*/ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 40a50167-a81c-463a-9e1d-3282ff84e09d */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** This is the OKI / Dialogic ADPCM encoder/decoder. It converts from ** 12 bit linear sample data to a 4 bit ADPCM. ** ** Implemented from the description found here: ** ** http://www.comptek.ru:8100/telephony/tnotes/tt1-13.html ** ** and compared against the encoder/decoder found here: ** ** http://ibiblio.org/pub/linux/apps/sound/convert/vox.tar.gz */ #include #include #include #define VOX_DATA_LEN 2048 #define PCM_DATA_LEN (VOX_DATA_LEN *2) typedef struct { short last ; short step_index ; int vox_bytes, pcm_samples ; unsigned char vox_data [VOX_DATA_LEN] ; short pcm_data [PCM_DATA_LEN] ; } VOX_ADPCM_PRIVATE ; static int vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) ; static int vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) ; static short vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) ; static char vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) ; static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t vox_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t vox_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t vox_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t vox_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static int vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ; static int vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ; /*============================================================================================ ** Predefined OKI ADPCM encoder/decoder tables. */ static short stepvox_adpcm_size_table [49] = { 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1408, 1552 } ; /* stepvox_adpcm_size_table */ static short stepvox_adpcm_adjust_table [8] = { -1, -1, -1, -1, 2, 4, 6, 8 } ; /* stepvox_adpcm_adjust_table */ /*------------------------------------------------------------------------------ */ int vox_adpcm_init (SF_PRIVATE *psf) { VOX_ADPCM_PRIVATE *pvox = NULL ; if (psf->mode == SFM_RDWR) return SFE_BAD_MODE_RW ; if (psf->mode == SFM_WRITE && psf->sf.channels != 1) return SFE_CHANNEL_COUNT ; if ((pvox = malloc (sizeof (VOX_ADPCM_PRIVATE))) == NULL) return SFE_MALLOC_FAILED ; psf->fdata = (void*) pvox ; memset (pvox, 0, sizeof (VOX_ADPCM_PRIVATE)) ; if (psf->mode == SFM_WRITE) { psf->write_short = vox_write_s ; psf->write_int = vox_write_i ; psf->write_float = vox_write_f ; psf->write_double = vox_write_d ; } else { psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.\n") ; psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.\n") ; psf->read_short = vox_read_s ; psf->read_int = vox_read_i ; psf->read_float = vox_read_f ; psf->read_double = vox_read_d ; } ; /* Standard sample rate chennels etc. */ if (psf->sf.samplerate < 1) psf->sf.samplerate = 8000 ; psf->sf.channels = 1 ; psf->sf.frames = psf->filelength * 2 ; psf->sf.seekable = SF_FALSE ; /* Seek back to start of data. */ if (psf_fseek (psf, 0 , SEEK_SET) == -1) return SFE_BAD_SEEK ; return 0 ; } /* vox_adpcm_init */ /*------------------------------------------------------------------------------ */ static char vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) { short code ; short diff, error, stepsize ; stepsize = stepvox_adpcm_size_table [pvox->step_index] ; code = 0 ; diff = samp - pvox->last ; if (diff < 0) { code = 0x08 ; error = -diff ; } else error = diff ; if (error >= stepsize) { code = code | 0x04 ; error -= stepsize ; } ; if (error >= stepsize / 2) { code = code | 0x02 ; error -= stepsize / 2 ; } ; if (error >= stepsize / 4) code = code | 0x01 ; /* ** To close the feedback loop, the deocder is used to set the ** estimate of last sample and in doing so, also set the step_index. */ pvox->last = vox_adpcm_decode (code, pvox) ; return code ; } /* vox_adpcm_encode */ static short vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) { short diff, error, stepsize, samp ; stepsize = stepvox_adpcm_size_table [pvox->step_index] ; error = stepsize / 8 ; if (code & 0x01) error += stepsize / 4 ; if (code & 0x02) error += stepsize / 2 ; if (code & 0x04) error += stepsize ; diff = (code & 0x08) ? -error : error ; samp = pvox->last + diff ; /* ** Apply clipping. */ if (samp > 2048) samp = 2048 ; if (samp < -2048) samp = -2048 ; pvox->last = samp ; pvox->step_index += stepvox_adpcm_adjust_table [code & 0x7] ; if (pvox->step_index < 0) pvox->step_index = 0 ; if (pvox->step_index > 48) pvox->step_index = 48 ; return samp ; } /* vox_adpcm_decode */ static int vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) { unsigned char code ; int j, k ; /* If data_count is odd, add an extra zero valued sample. */ if (pvox->pcm_samples & 1) pvox->pcm_data [pvox->pcm_samples++] = 0 ; for (j = k = 0 ; k < pvox->pcm_samples ; j++) { code = vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) << 4 ; code |= vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) ; pvox->vox_data [j] = code ; } ; pvox->vox_bytes = j ; return 0 ; } /* vox_adpcm_encode_block */ static int vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) { unsigned char code ; int j, k ; for (j = k = 0 ; j < pvox->vox_bytes ; j++) { code = pvox->vox_data [j] ; pvox->pcm_data [k++] = 16 * vox_adpcm_decode ((code >> 4) & 0x0f, pvox) ; pvox->pcm_data [k++] = 16 * vox_adpcm_decode (code & 0x0f, pvox) ; } ; pvox->pcm_samples = k ; return 0 ; } /* vox_adpcm_decode_block */ /*============================================================================== */ static int vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) { int indx = 0, k ; while (indx < len) { pvox->vox_bytes = (len - indx > PCM_DATA_LEN) ? VOX_DATA_LEN : (len - indx + 1) / 2 ; if ((k = psf_fread (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes) { if (psf_ftell (psf) + k != psf->filelength) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ; if (k == 0) break ; } ; pvox->vox_bytes = k ; vox_adpcm_decode_block (pvox) ; memcpy (&(ptr [indx]), pvox->pcm_data, pvox->pcm_samples * sizeof (short)) ; indx += pvox->pcm_samples ; } ; return indx ; } /* vox_read_block */ static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; int readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; while (len > 0) { readcount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = vox_read_block (psf, pvox, ptr, readcount) ; total += count ; len -= count ; if (count != readcount) break ; } ; return total ; } /* vox_read_s */ static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = vox_read_block (psf, pvox, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = ((int) sptr [k]) << 16 ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* vox_read_i */ static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = vox_read_block (psf, pvox, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (float) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* vox_read_f */ static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, readcount, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; count = vox_read_block (psf, pvox, sptr, readcount) ; for (k = 0 ; k < readcount ; k++) ptr [total + k] = normfact * (double) (sptr [k]) ; total += count ; len -= readcount ; if (count != readcount) break ; } ; return total ; } /* vox_read_d */ /*------------------------------------------------------------------------------ */ static int vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) { int indx = 0, k ; while (indx < len) { pvox->pcm_samples = (len - indx > PCM_DATA_LEN) ? PCM_DATA_LEN : len - indx ; memcpy (pvox->pcm_data, &(ptr [indx]), pvox->pcm_samples * sizeof (short)) ; vox_adpcm_encode_block (pvox) ; if ((k = psf_fwrite (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes) psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ; indx += pvox->pcm_samples ; } ; return indx ; } /* vox_write_block */ static sf_count_t vox_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; int writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; while (len) { writecount = (len > 0x10000000) ? 0x10000000 : (int) len ; count = vox_write_block (psf, pvox, ptr, writecount) ; total += count ; len -= count ; if (count != writecount) break ; } ; return total ; } /* vox_write_s */ static sf_count_t vox_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = ptr [total + k] >> 16 ; count = vox_write_block (psf, pvox, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* vox_write_i */ static sf_count_t vox_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; float normfact ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrintf (normfact * ptr [total + k]) ; count = vox_write_block (psf, pvox, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* vox_write_f */ static sf_count_t vox_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { VOX_ADPCM_PRIVATE *pvox ; short *sptr ; int k, bufferlen, writecount, count ; sf_count_t total = 0 ; double normfact ; if (! psf->fdata) return 0 ; pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; sptr = (short*) psf->buffer ; bufferlen = SF_BUFFER_LEN / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; for (k = 0 ; k < writecount ; k++) sptr [k] = lrint (normfact * ptr [total + k]) ; count = vox_write_block (psf, pvox, sptr, writecount) ; total += count ; len -= writecount ; if (count != writecount) break ; } ; return total ; } /* vox_write_d */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: e15e97fe-ff9d-4b46-a489-7059fb2d0b1e */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ ** W64 files use 16 byte markers as opposed to the four byte marker of ** WAV files. ** For comparison purposes, an integer is required, so make an integer ** hash for the 16 bytes using MAKE_HASH16 macro, but also create a 16 ** byte array containing the complete 16 bytes required when writing the ** header. */ #define MAKE_HASH16(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \ ( (x0) ^ ((x1) << 1) ^ ((x2) << 2) ^ ((x3) << 3) ^ \ ((x4) << 4) ^ ((x5) << 5) ^ ((x6) << 6) ^ ((x7) << 7) ^ \ ((x8) << 8) ^ ((x9) << 9) ^ ((xa) << 10) ^ ((xb) << 11) ^ \ ((xc) << 12) ^ ((xd) << 13) ^ ((xe) << 14) ^ ((xf) << 15) ) #define MAKE_MARKER16(name,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \ static unsigned char name [16] = { (x0), (x1), (x2), (x3), (x4), (x5), \ (x6), (x7), (x8), (x9), (xa), (xb), (xc), (xd), (xe), (xf) } #define riff_HASH16 MAKE_HASH16 ('r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, \ 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) #define wave_HASH16 MAKE_HASH16 ('w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, \ 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) #define fmt_HASH16 MAKE_HASH16 ('f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, \ 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) #define fact_HASH16 MAKE_HASH16 ('f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, \ 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) #define data_HASH16 MAKE_HASH16 ('d', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, \ 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) #define ACID_HASH16 MAKE_HASH16 (0x6D, 0x07, 0x1C, 0xEA, 0xA3, 0xEF, 0x78, 0x4C, \ 0x90, 0x57, 0x7F, 0x79, 0xEE, 0x25, 0x2A, 0xAE) MAKE_MARKER16 (riff_MARKER16, 'r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) ; MAKE_MARKER16 (wave_MARKER16, 'w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; MAKE_MARKER16 (fmt_MARKER16, 'f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; MAKE_MARKER16 (fact_MARKER16, 'f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; MAKE_MARKER16 (data_MARKER16, 'd', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ; enum { HAVE_riff = 0x01, HAVE_wave = 0x02, w64HAVE_fmt = 0x04, w64HAVE_fact = 0x08, w64HAVE_data = 0x20 } ; /*------------------------------------------------------------------------------ * Private static functions. */ static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ; static int w64_write_header (SF_PRIVATE *psf, int calc_length) ; static int w64_close (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int w64_open (SF_PRIVATE *psf) { int subformat, error, blockalign = 0, framesperblock = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR &&psf->filelength > 0)) { if ((error = w64_read_header (psf, &blockalign, &framesperblock))) return error ; } ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_W64) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; psf->endian = SF_ENDIAN_LITTLE ; /* All W64 files are little endian. */ psf->blockwidth = psf->bytewidth * psf->sf.channels ; if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) { blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = -1 ; /* FIXME : This block must go */ psf->filelength = SF_COUNT_MAX ; psf->datalength = psf->filelength ; if (psf->sf.frames <= 0) psf->sf.frames = (psf->blockwidth) ? psf->filelength / psf->blockwidth : psf->filelength ; /* EMXIF : This block must go */ } ; if ((error = w64_write_header (psf, SF_FALSE))) return error ; psf->write_header = w64_write_header ; } ; psf->close = w64_close ; switch (subformat) { case SF_FORMAT_PCM_U8 : error = pcm_init (psf) ; break ; case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; /* Lite remove start */ case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; case SF_FORMAT_IMA_ADPCM : error = wav_w64_ima_init (psf, blockalign, framesperblock) ; break ; case SF_FORMAT_MS_ADPCM : error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : error = gsm610_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; return error ; } /* w64_open */ /*========================================================================= ** Private functions. */ static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) { WAV_FMT wav_fmt ; int dword = 0, marker, format = 0 ; sf_count_t chunk_size, bytesread = 0 ; int parsestage = 0, error, done = 0 ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "p", 0) ; while (! done) { /* Read the 4 byte marker and jump 12 bytes. */ bytesread += psf_binheader_readf (psf, "h", &marker) ; chunk_size = 0 ; switch (marker) { case riff_HASH16 : if (parsestage) return SFE_W64_NO_RIFF ; bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; if (psf->filelength < chunk_size) psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ; else psf_log_printf (psf, "riff : %D\n", chunk_size) ; parsestage |= HAVE_riff ; break ; case ACID_HASH16: psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ; return SFE_UNIMPLEMENTED ; case wave_HASH16 : if ((parsestage & HAVE_riff) != HAVE_riff) return SFE_W64_NO_WAVE ; psf_log_printf (psf, "wave\n") ; parsestage |= HAVE_wave ; break ; case fmt_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave)) return SFE_W64_NO_FMT ; bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, " fmt : %D\n", chunk_size) ; /* size of 16 byte marker and 8 byte chunk_size value. */ chunk_size -= 24 ; if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size))) return error ; if (chunk_size % 8) psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ; format = wav_fmt.format ; parsestage |= w64HAVE_fmt ; break ; case fact_HASH16: { sf_count_t frames ; psf_binheader_readf (psf, "e88", &chunk_size, &frames) ; psf_log_printf (psf, " fact : %D\n frames : %D\n", chunk_size, frames) ; } ; break ; case data_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave | w64HAVE_fmt)) != (HAVE_riff | HAVE_wave | w64HAVE_fmt)) return SFE_W64_NO_DATA ; psf_binheader_readf (psf, "e8", &chunk_size) ; psf->dataoffset = psf_ftell (psf) ; psf->datalength = chunk_size - 24 ; if (chunk_size % 8) chunk_size += 8 - (chunk_size % 8) ; psf_log_printf (psf, "data : %D\n", chunk_size) ; parsestage |= w64HAVE_data ; if (! psf->sf.seekable) break ; /* Seek past data and continue reading header. */ psf_fseek (psf, chunk_size, SEEK_CUR) ; break ; default : if (psf_ftell (psf) & 0x0F) { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; psf_binheader_readf (psf, "j", -3) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; done = SF_TRUE ; break ; } ; /* switch (dword) */ if (psf->sf.seekable == 0 && (parsestage & w64HAVE_data)) break ; if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword)))) break ; if (psf->logindex >= SIGNED_SIZEOF (psf->logbuffer) - 2) return SFE_LOG_OVERRUN ; } ; /* while (1) */ if (! psf->dataoffset) return SFE_W64_NO_DATA ; psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */ if (psf_ftell (psf) != psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; psf->close = w64_close ; if (psf->blockwidth) { if (psf->filelength - psf->dataoffset < psf->datalength) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; else psf->sf.frames = psf->datalength / psf->blockwidth ; } ; switch (format) { case WAVE_FORMAT_PCM : case WAVE_FORMAT_EXTENSIBLE : /* extensible might be FLOAT, MULAW, etc as well! */ psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ; break ; case WAVE_FORMAT_MULAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ; break ; case WAVE_FORMAT_ALAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ; break ; case WAVE_FORMAT_MS_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM) ; *blockalign = wav_fmt.msadpcm.blockalign ; *framesperblock = wav_fmt.msadpcm.samplesperblock ; break ; case WAVE_FORMAT_IMA_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM) ; *blockalign = wav_fmt.ima.blockalign ; *framesperblock = wav_fmt.ima.samplesperblock ; break ; case WAVE_FORMAT_GSM610 : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ; break ; case WAVE_FORMAT_IEEE_FLOAT : psf->sf.format = SF_FORMAT_W64 ; psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; break ; default : return SFE_UNIMPLEMENTED ; } ; return 0 ; } /* w64_read_header */ static int w64_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t fmt_size, current ; size_t fmt_pad = 0 ; int subformat, add_fact_chunk = SF_FALSE ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* riff marker, length, wave and 'fmt ' markers. */ psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength - 8, wave_MARKER16, fmt_MARKER16) ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; break ; case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ULAW : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ALAW : fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove start */ case SF_FORMAT_IMA_ADPCM : { int blockalign, framesperblock, bytespersec ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ; } ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_MS_ADPCM : { int blockalign, framesperblock, bytespersec, extrabytes ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ; fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, W64 format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ; msadpcm_write_adapt_coeffs (psf) ; } ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : { int bytespersec ; bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ; /* fmt chunk. */ fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ; fmt_size += fmt_pad ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ; } ; add_fact_chunk = SF_TRUE ; break ; default : return SFE_UNIMPLEMENTED ; } ; /* Pad to 8 bytes with zeros. */ if (fmt_pad > 0) psf_binheader_writef (psf, "z", fmt_pad) ; if (add_fact_chunk) psf_binheader_writef (psf, "eh88", fact_MARKER16, 16 + 8 + 8, psf->sf.frames) ; psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* w64_write_header */ static int w64_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) w64_write_header (psf, SF_TRUE) ; return 0 ; } /* w64_close */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 9aa4e141-538a-4dd9-99c9-b3f0f2dd4f4a */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** Copyright (C) 2004 David Viens ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include /*------------------------------------------------------------------------------ * Macros to handle big/little endian issues. */ #define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F')) #define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E')) #define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' ')) #define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a')) #define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't')) #define PEAK_MARKER (MAKE_MARKER ('P', 'E', 'A', 'K')) #define cue_MARKER (MAKE_MARKER ('c', 'u', 'e', ' ')) #define LIST_MARKER (MAKE_MARKER ('L', 'I', 'S', 'T')) #define slnt_MARKER (MAKE_MARKER ('s', 'l', 'n', 't')) #define wavl_MARKER (MAKE_MARKER ('w', 'a', 'v', 'l')) #define INFO_MARKER (MAKE_MARKER ('I', 'N', 'F', 'O')) #define plst_MARKER (MAKE_MARKER ('p', 'l', 's', 't')) #define adtl_MARKER (MAKE_MARKER ('a', 'd', 't', 'l')) #define labl_MARKER (MAKE_MARKER ('l', 'a', 'b', 'l')) #define ltxt_MARKER (MAKE_MARKER ('l', 't', 'x', 't')) #define note_MARKER (MAKE_MARKER ('n', 'o', 't', 'e')) #define smpl_MARKER (MAKE_MARKER ('s', 'm', 'p', 'l')) #define bext_MARKER (MAKE_MARKER ('b', 'e', 'x', 't')) #define MEXT_MARKER (MAKE_MARKER ('M', 'E', 'X', 'T')) #define DISP_MARKER (MAKE_MARKER ('D', 'I', 'S', 'P')) #define acid_MARKER (MAKE_MARKER ('a', 'c', 'i', 'd')) #define strc_MARKER (MAKE_MARKER ('s', 't', 'r', 'c')) #define PAD_MARKER (MAKE_MARKER ('P', 'A', 'D', ' ')) #define afsp_MARKER (MAKE_MARKER ('a', 'f', 's', 'p')) #define clm_MARKER (MAKE_MARKER ('c', 'l', 'm', ' ')) #define ISFT_MARKER (MAKE_MARKER ('I', 'S', 'F', 'T')) #define ICRD_MARKER (MAKE_MARKER ('I', 'C', 'R', 'D')) #define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P')) #define IARL_MARKER (MAKE_MARKER ('I', 'A', 'R', 'L')) #define IART_MARKER (MAKE_MARKER ('I', 'A', 'R', 'T')) #define INAM_MARKER (MAKE_MARKER ('I', 'N', 'A', 'M')) #define IENG_MARKER (MAKE_MARKER ('I', 'E', 'N', 'G')) #define IART_MARKER (MAKE_MARKER ('I', 'A', 'R', 'T')) #define ICOP_MARKER (MAKE_MARKER ('I', 'C', 'O', 'P')) #define IPRD_MARKER (MAKE_MARKER ('I', 'P', 'R', 'D')) #define ISRC_MARKER (MAKE_MARKER ('I', 'S', 'R', 'C')) #define ISBJ_MARKER (MAKE_MARKER ('I', 'S', 'B', 'J')) #define ICMT_MARKER (MAKE_MARKER ('I', 'C', 'M', 'T')) /* Weird WAVPACK marker which can show up at the start of the DATA section. */ #define wvpk_MARKER (MAKE_MARKER ('w', 'v', 'p', 'k')) #define OggS_MARKER (MAKE_MARKER ('O', 'g', 'g', 'S')) enum { HAVE_RIFF = 0x01, HAVE_WAVE = 0x02, wavHAVE_fmt = 0x04, wavHAVE_fact = 0x08, HAVE_PEAK = 0x10, wavHAVE_data = 0x20, HAVE_other = 0x80000000 } ; /* known WAVEFORMATEXTENSIBLE GUIDS */ static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = { 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } ; static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM = { 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } ; static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT = { 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } ; static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW = { 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } ; static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW = { 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } } ; #if 0 /* maybe interesting one day to read the following through sf_read_raw */ /* http://www.bath.ac.uk/~masrwd/pvocex/pvocex.html */ static const EXT_SUBFORMAT MSGUID_SUBTYPE_PVOCEX = { 0x8312B9C2, 0x2E6E, 0x11d4, { 0xA8, 0x24, 0xDE, 0x5B, 0x96, 0xC3, 0xAB, 0x21 } } ; #endif /*------------------------------------------------------------------------------ ** Private static functions. */ static int wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ; static int wav_write_header (SF_PRIVATE *psf, int calc_length) ; static void wavex_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) ; static int wavex_write_header (SF_PRIVATE *psf, int calc_length) ; static int wav_write_tailer (SF_PRIVATE *psf) ; static void wav_write_strings (SF_PRIVATE *psf, int location) ; static int wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) ; static int wav_close (SF_PRIVATE *psf) ; static int wav_subchunk_parse (SF_PRIVATE *psf, int chunk) ; static int wav_read_smpl_chunk (SF_PRIVATE *psf, unsigned int chunklen) ; static int wav_read_acid_chunk (SF_PRIVATE *psf, unsigned int chunklen) ; static int wavex_write_guid_equal (const EXT_SUBFORMAT * first, const EXT_SUBFORMAT * second) ; /*------------------------------------------------------------------------------ ** Public function. */ int wav_open (SF_PRIVATE *psf) { int format, subformat, error, blockalign = 0, framesperblock = 0 ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = wav_read_header (psf, &blockalign, &framesperblock))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if (psf->is_pipe) return SFE_NO_PIPE_WRITE ; format = psf->sf.format & SF_FORMAT_TYPEMASK ; if (format != SF_FORMAT_WAV && format != SF_FORMAT_WAVEX) return SFE_BAD_OPEN_FORMAT ; psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */ psf->blockwidth = psf->bytewidth * psf->sf.channels ; if (psf->mode != SFM_RDWR || psf->filelength < 44) { psf->filelength = 0 ; psf->datalength = 0 ; psf->dataoffset = 0 ; psf->sf.frames = 0 ; } ; if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM) { blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = -1 ; /* Corrected later. */ } ; psf->str_flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; /* By default, add the peak chunk to floating point files. Default behaviour ** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE). */ if (psf->mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE)) { psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; psf->has_peak = SF_TRUE ; psf->peak_loc = SF_PEAK_START ; } ; psf->write_header = (format == SF_FORMAT_WAV) ? wav_write_header : wavex_write_header ; } ; psf->close = wav_close ; psf->command = wav_command ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : error = pcm_init (psf) ; break ; case SF_FORMAT_ULAW : error = ulaw_init (psf) ; break ; case SF_FORMAT_ALAW : error = alaw_init (psf) ; break ; /* Lite remove start */ case SF_FORMAT_FLOAT : error = float32_init (psf) ; break ; case SF_FORMAT_DOUBLE : error = double64_init (psf) ; break ; case SF_FORMAT_IMA_ADPCM : error = wav_w64_ima_init (psf, blockalign, framesperblock) ; break ; case SF_FORMAT_MS_ADPCM : error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : error = gsm610_init (psf) ; break ; default : return SFE_UNIMPLEMENTED ; } ; if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->filelength == 0)) return psf->write_header (psf, SF_FALSE) ; return error ; } /* wav_open */ /*========================================================================= ** Private functions. */ static int wav_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) { WAV_FMT wav_fmt ; FACT_CHUNK fact_chunk ; int dword, marker, RIFFsize, done = 0 ; int parsestage = 0, error, format = 0 ; char *cptr ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "p", 0) ; while (! done) { psf_binheader_readf (psf, "m", &marker) ; switch (marker) { case RIFF_MARKER : if (parsestage) return SFE_WAV_NO_RIFF ; parsestage |= HAVE_RIFF ; psf_binheader_readf (psf, "e4", &RIFFsize) ; if (psf->fileoffset > 0 && psf->filelength > RIFFsize + 8) { /* Set file length. */ psf->filelength = RIFFsize + 8 ; psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ; } else if (psf->filelength < RIFFsize + 2 * SIGNED_SIZEOF (dword)) { psf_log_printf (psf, "RIFF : %u (should be %D)\n", RIFFsize, psf->filelength - 2 * SIGNED_SIZEOF (dword)) ; RIFFsize = dword ; } else psf_log_printf (psf, "RIFF : %u\n", RIFFsize) ; break ; case WAVE_MARKER : if ((parsestage & HAVE_RIFF) != HAVE_RIFF) return SFE_WAV_NO_WAVE ; parsestage |= HAVE_WAVE ; psf_log_printf (psf, "WAVE\n") ; break ; case fmt_MARKER : if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE)) return SFE_WAV_NO_FMT ; /* If this file has a SECOND fmt chunk, I don't want to know about it. */ if (parsestage & wavHAVE_fmt) break ; parsestage |= wavHAVE_fmt ; psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "fmt : %d\n", dword) ; if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, dword))) return error ; format = wav_fmt.format ; break ; case data_MARKER : if ((parsestage & (HAVE_RIFF | HAVE_WAVE | wavHAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | wavHAVE_fmt)) return SFE_WAV_NO_DATA ; if (psf->mode == SFM_RDWR && (parsestage & HAVE_other) != 0) return SFE_RDWR_BAD_HEADER ; parsestage |= wavHAVE_data ; psf_binheader_readf (psf, "e4", &dword) ; psf->datalength = dword ; psf->dataoffset = psf_ftell (psf) ; if (dword == 0 && RIFFsize == 8 && psf->filelength > 44) { psf_log_printf (psf, "*** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ; psf->datalength = dword = psf->filelength - psf->dataoffset ; } ; if (psf->datalength > psf->filelength - psf->dataoffset) { psf_log_printf (psf, "data : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ; psf->datalength = psf->filelength - psf->dataoffset ; } else psf_log_printf (psf, "data : %D\n", psf->datalength) ; /* Only set dataend if there really is data at the end. */ if (psf->datalength + psf->dataoffset < psf->filelength) psf->dataend = psf->datalength + psf->dataoffset ; if (format == WAVE_FORMAT_MS_ADPCM && psf->datalength % 2) { psf->datalength ++ ; psf_log_printf (psf, "*** Data length odd. Increasing it by 1.\n") ; } ; if (! psf->sf.seekable) break ; /* Seek past data and continue reading header. */ psf_fseek (psf, psf->datalength, SEEK_CUR) ; dword = psf_ftell (psf) ; if (dword != (sf_count_t) (psf->dataoffset + psf->datalength)) psf_log_printf (psf, "*** psf_fseek past end error ***\n", dword, psf->dataoffset + psf->datalength) ; break ; case fact_MARKER : if ((parsestage & (HAVE_RIFF | HAVE_WAVE)) != (HAVE_RIFF | HAVE_WAVE)) return SFE_WAV_BAD_FACT ; parsestage |= wavHAVE_fact ; if ((parsestage & wavHAVE_fmt) != wavHAVE_fmt) psf_log_printf (psf, "*** Should have 'fmt ' chunk before 'fact'\n") ; psf_binheader_readf (psf, "e44", &dword, & (fact_chunk.frames)) ; if (dword > SIGNED_SIZEOF (fact_chunk)) psf_binheader_readf (psf, "j", (int) (dword - SIGNED_SIZEOF (fact_chunk))) ; if (dword) psf_log_printf (psf, "%M : %d\n", marker, dword) ; else psf_log_printf (psf, "%M : %d (should not be zero)\n", marker, dword) ; psf_log_printf (psf, " frames : %d\n", fact_chunk.frames) ; break ; case PEAK_MARKER : if ((parsestage & (HAVE_RIFF | HAVE_WAVE | wavHAVE_fmt)) != (HAVE_RIFF | HAVE_WAVE | wavHAVE_fmt)) return SFE_WAV_PEAK_B4_FMT ; parsestage |= HAVE_PEAK ; psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "%M : %d\n", marker, dword) ; if (dword != SIGNED_SIZEOF (PEAK_CHUNK) + psf->sf.channels * SIGNED_SIZEOF (PEAK_POS)) { psf_binheader_readf (psf, "j", dword) ; psf_log_printf (psf, "*** File PEAK chunk size doesn't fit with number of channels.\n") ; return SFE_WAV_BAD_PEAK ; } ; psf->pchunk = calloc (1, sizeof (PEAK_CHUNK) * psf->sf.channels * sizeof (PEAK_POS)) ; if (psf->pchunk == NULL) return SFE_MALLOC_FAILED ; /* read in rest of PEAK chunk. */ psf_binheader_readf (psf, "e44", & (psf->pchunk->version), & (psf->pchunk->timestamp)) ; if (psf->pchunk->version != 1) psf_log_printf (psf, " version : %d *** (should be version 1)\n", psf->pchunk->version) ; else psf_log_printf (psf, " version : %d\n", psf->pchunk->version) ; psf_log_printf (psf, " time stamp : %d\n", psf->pchunk->timestamp) ; psf_log_printf (psf, " Ch Position Value\n") ; cptr = (char *) psf->buffer ; for (dword = 0 ; dword < psf->sf.channels ; dword++) { psf_binheader_readf (psf, "ef4", & (psf->pchunk->peaks [dword].value), & (psf->pchunk->peaks [dword].position)) ; LSF_SNPRINTF (cptr, sizeof (psf->buffer), " %2d %-12d %g\n", dword, psf->pchunk->peaks [dword].position, psf->pchunk->peaks [dword].value) ; cptr [sizeof (psf->buffer) - 1] = 0 ; psf_log_printf (psf, cptr) ; } ; psf->has_peak = SF_TRUE ; /* Found PEAK chunk. */ psf->peak_loc = ((parsestage & wavHAVE_data) == 0) ? SF_PEAK_START : SF_PEAK_END ; break ; case cue_MARKER : parsestage |= HAVE_other ; { int bytesread, cue_count ; int id, position, chunk_id, chunk_start, block_start, offset ; bytesread = psf_binheader_readf (psf, "e44", &dword, &cue_count) ; bytesread -= 4 ; /* Remove bytes for first dword. */ psf_log_printf (psf, "%M : %u\n Count : %d\n", marker, dword, cue_count) ; while (cue_count) { bytesread += psf_binheader_readf (psf, "e444444", &id, &position, &chunk_id, &chunk_start, &block_start, &offset) ; psf_log_printf (psf, " Cue ID : %2d" " Pos : %5u Chunk : %M" " Chk Start : %d Blk Start : %d" " Offset : %5d\n", id, position, chunk_id, chunk_start, block_start, offset) ; cue_count -- ; } ; if (bytesread != dword) { psf_log_printf (psf, "**** Chunk size weirdness (%d != %d)\n", dword, bytesread) ; psf_binheader_readf (psf, "j", dword - bytesread) ; } ; } ; break ; case smpl_MARKER : parsestage |= HAVE_other ; psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "smpl : %u\n", dword) ; if ((error = wav_read_smpl_chunk (psf, dword))) return error ; break ; case acid_MARKER : parsestage |= HAVE_other ; psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "acid : %u\n", dword) ; if ((error = wav_read_acid_chunk (psf, dword))) return error ; break ; case INFO_MARKER : case LIST_MARKER : parsestage |= HAVE_other ; if ((error = wav_subchunk_parse (psf, marker)) != 0) return error ; break ; case strc_MARKER : /* Multiple of 32 bytes. */ case afsp_MARKER : case bext_MARKER : case clm_MARKER : case plst_MARKER : case DISP_MARKER : case MEXT_MARKER : case PAD_MARKER : parsestage |= HAVE_other ; psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "%M : %u\n", marker, dword) ; dword += (dword & 1) ; psf_binheader_readf (psf, "j", dword) ; break ; default : if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) { psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, dword) ; psf_binheader_readf (psf, "j", dword) ; break ; } ; if (psf_ftell (psf) & 0x03) { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; psf_binheader_readf (psf, "j", -3) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; done = SF_TRUE ; break ; } ; /* switch (dword) */ if (! psf->sf.seekable && (parsestage & wavHAVE_data)) break ; if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword)) { psf_log_printf (psf, "End\n") ; break ; } ; if (psf->logindex >= SIGNED_SIZEOF (psf->logbuffer) - 2) return SFE_LOG_OVERRUN ; } ; /* while (1) */ if (! psf->dataoffset) return SFE_WAV_NO_DATA ; psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */ psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if (psf->is_pipe == 0) { /* ** Check for 'wvpk' at the start of the DATA section. Not able to ** handle this. */ psf_binheader_readf (psf, "e4", &marker) ; if (marker == wvpk_MARKER || marker == OggS_MARKER) return SFE_WAV_WVPK_DATA ; } ; /* Seek to start of DATA section. */ psf_fseek (psf, psf->dataoffset, SEEK_SET) ; psf->close = wav_close ; if (psf->blockwidth) { if (psf->filelength - psf->dataoffset < psf->datalength) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; else psf->sf.frames = psf->datalength / psf->blockwidth ; } ; switch (format) { case WAVE_FORMAT_EXTENSIBLE : /* compare GUIDs for known ones */ if (wavex_write_guid_equal (&wav_fmt.ext.esf, &MSGUID_SUBTYPE_PCM)) psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; else if (wavex_write_guid_equal (&wav_fmt.ext.esf, &MSGUID_SUBTYPE_MS_ADPCM)) { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM) ; *blockalign = wav_fmt.msadpcm.blockalign ; *framesperblock = wav_fmt.msadpcm.samplesperblock ; } else if (wavex_write_guid_equal (&wav_fmt.ext.esf, &MSGUID_SUBTYPE_IEEE_FLOAT)) psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; else if (wavex_write_guid_equal (&wav_fmt.ext.esf, &MSGUID_SUBTYPE_ALAW)) psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ALAW) ; else if (wavex_write_guid_equal (&wav_fmt.ext.esf, &MSGUID_SUBTYPE_MULAW)) psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ULAW) ; else return SFE_UNIMPLEMENTED ; break ; case WAVE_FORMAT_PCM : psf->sf.format = SF_FORMAT_WAV | u_bitwidth_to_subformat (psf->bytewidth * 8) ; break ; case WAVE_FORMAT_MULAW : case IBM_FORMAT_MULAW : psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ULAW) ; break ; case WAVE_FORMAT_ALAW : case IBM_FORMAT_ALAW : psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_ALAW) ; break ; case WAVE_FORMAT_MS_ADPCM : psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM) ; *blockalign = wav_fmt.msadpcm.blockalign ; *framesperblock = wav_fmt.msadpcm.samplesperblock ; break ; case WAVE_FORMAT_IMA_ADPCM : psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM) ; *blockalign = wav_fmt.ima.blockalign ; *framesperblock = wav_fmt.ima.samplesperblock ; break ; case WAVE_FORMAT_GSM610 : psf->sf.format = (SF_FORMAT_WAV | SF_FORMAT_GSM610) ; break ; case WAVE_FORMAT_IEEE_FLOAT : psf->sf.format = SF_FORMAT_WAV ; psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; break ; default : return SFE_UNIMPLEMENTED ; } ; return 0 ; } /* wav_read_header */ static int wav_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int fmt_size, k, subformat, add_fact_chunk = SF_FALSE ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* RIFF marker, length, WAVE and 'fmt ' markers. */ if (psf->filelength < 8) psf_binheader_writef (psf, "etm8", RIFF_MARKER, 8) ; else psf_binheader_writef (psf, "etm8", RIFF_MARKER, psf->filelength - 8) ; /* WAVE and 'fmt ' markers. */ psf_binheader_writef (psf, "emm", WAVE_MARKER, fmt_MARKER) ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e4224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; break ; case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e4224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ULAW : fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e4224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ALAW : fmt_size = 2 + 2 + 4 + 4 + 2 + 2 ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e4224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove start */ case SF_FORMAT_IMA_ADPCM : { int blockalign, framesperblock, bytespersec ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; /* fmt : size, WAV format type, channels, samplerate, bytespersec */ psf_binheader_writef (psf, "e42244", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels, psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ; } ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_MS_ADPCM : { int blockalign, framesperblock, bytespersec, extrabytes ; blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ; framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ; fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e422", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ; msadpcm_write_adapt_coeffs (psf) ; } ; add_fact_chunk = SF_TRUE ; break ; /* Lite remove end */ case SF_FORMAT_GSM610 : { int blockalign, framesperblock, bytespersec ; blockalign = WAV_W64_GSM610_BLOCKSIZE ; framesperblock = WAV_W64_GSM610_SAMPLES ; bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ; /* fmt chunk. */ fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ; /* fmt : size, WAV format type, channels. */ psf_binheader_writef (psf, "e422", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ; /* fmt : samplerate, bytespersec. */ psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ; /* fmt : blockalign, bitwidth, extrabytes, framesperblock. */ psf_binheader_writef (psf, "e2222", blockalign, 0, 2, framesperblock) ; } ; add_fact_chunk = SF_TRUE ; break ; default : return SFE_UNIMPLEMENTED ; } ; if (add_fact_chunk) psf_binheader_writef (psf, "etm48", fact_MARKER, 4, psf->sf.frames) ; if (psf->str_flags & SF_STR_LOCATE_START) wav_write_strings (psf, SF_STR_LOCATE_START) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_START) { psf_binheader_writef (psf, "em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "e44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; } ; psf_binheader_writef (psf, "etm8", data_MARKER, psf->datalength) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* wav_write_header */ static int wavex_write_guid_equal (const EXT_SUBFORMAT * first, const EXT_SUBFORMAT * second) { return !memcmp (first, second, sizeof (EXT_SUBFORMAT)) ; } /* wavex_write_guid_equal */ static void wavex_write_guid (SF_PRIVATE *psf, const EXT_SUBFORMAT * subformat) { psf_binheader_writef (psf, "e422b", subformat->esf_field1, subformat->esf_field2, subformat->esf_field3, subformat->esf_field4, 8) ; } /* wavex_write_guid */ static int wavex_write_header (SF_PRIVATE *psf, int calc_length) { sf_count_t current ; int fmt_size, k, subformat, add_fact_chunk = SF_FALSE ; current = psf_ftell (psf) ; if (calc_length) { psf->filelength = psf_get_filelen (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->dataend) psf->datalength -= psf->filelength - psf->dataend ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; } ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; /* RIFF marker, length, WAVE and 'fmt ' markers. */ if (psf->filelength < 8) psf_binheader_writef (psf, "etm8", RIFF_MARKER, 8) ; else psf_binheader_writef (psf, "etm8", RIFF_MARKER, psf->filelength - 8) ; /* WAVE and 'fmt ' markers. */ psf_binheader_writef (psf, "emm", WAVE_MARKER, fmt_MARKER) ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; /* initial section (same for all, it appears) */ switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : case SF_FORMAT_ULAW : case SF_FORMAT_ALAW : fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ; /* fmt : format, channels, samplerate */ psf_binheader_writef (psf, "e4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ; /* fmt : bytespersec */ psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ; /* fmt : blockalign, bitwidth */ psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ; /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */ psf_binheader_writef (psf, "e2", 22) ; /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */ psf_binheader_writef (psf, "e2", psf->bytewidth * 8) ; if (psf->sf.channels == 2) psf_binheader_writef (psf, "e4", 0x1 | 0x2 ) ; /* dwChannelMask front left and right */ else psf_binheader_writef (psf, "e4", 0) ; /* dwChannelMask = 0 when in doubt */ break ; case SF_FORMAT_MS_ADPCM : /* todo, GUID exists might have different header as per wav_write_header */ default : return SFE_UNIMPLEMENTED ; } ; /* GUI section, different for each */ switch (subformat) { case SF_FORMAT_PCM_U8 : case SF_FORMAT_PCM_16 : case SF_FORMAT_PCM_24 : case SF_FORMAT_PCM_32 : wavex_write_guid (psf, &MSGUID_SUBTYPE_PCM) ; break ; case SF_FORMAT_FLOAT : case SF_FORMAT_DOUBLE : wavex_write_guid (psf, &MSGUID_SUBTYPE_IEEE_FLOAT) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ULAW : wavex_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_ALAW : wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ; add_fact_chunk = SF_TRUE ; break ; case SF_FORMAT_MS_ADPCM : /* todo, GUID exists */ default : return SFE_UNIMPLEMENTED ; } ; if (add_fact_chunk) psf_binheader_writef (psf, "etm48", fact_MARKER, 4, psf->sf.frames) ; if (psf->str_flags & SF_STR_LOCATE_START) wav_write_strings (psf, SF_STR_LOCATE_START) ; if (psf->has_peak && psf->peak_loc == SF_PEAK_START) { psf_binheader_writef (psf, "em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "e44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; } ; psf_binheader_writef (psf, "etm8", data_MARKER, psf->datalength) ; psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current < psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; else if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* wavex_write_header */ static int wav_write_tailer (SF_PRIVATE *psf) { int k ; /* Reset the current header buffer length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf->dataend = psf_fseek (psf, 0, SEEK_END) ; /* Add a PEAK chunk if requested. */ if (psf->has_peak && psf->peak_loc == SF_PEAK_END) { psf_binheader_writef (psf, "em4", PEAK_MARKER, sizeof (PEAK_CHUNK) + psf->sf.channels * sizeof (PEAK_POS)) ; psf_binheader_writef (psf, "e44", 1, time (NULL)) ; for (k = 0 ; k < psf->sf.channels ; k++) psf_binheader_writef (psf, "ef4", psf->pchunk->peaks [k].value, psf->pchunk->peaks [k].position) ; } ; if (psf->str_flags & SF_STR_LOCATE_END) wav_write_strings (psf, SF_STR_LOCATE_END) ; /* Write the tailer. */ if (psf->headindex > 0) psf_fwrite (psf->header, psf->headindex, 1, psf) ; return 0 ; } /* wav_write_tailer */ static void wav_write_strings (SF_PRIVATE *psf, int location) { int k, prev_head_index, saved_head_index ; prev_head_index = psf->headindex + 4 ; psf_binheader_writef (psf, "em4m", LIST_MARKER, 0xBADBAD, INFO_MARKER) ; for (k = 0 ; k < SF_MAX_STRINGS ; k++) { if (psf->strings [k].type == 0) break ; if (psf->strings [k].flags != location) continue ; switch (psf->strings [k].type) { case SF_STR_SOFTWARE : psf_binheader_writef (psf, "ems", ISFT_MARKER, psf->strings [k].str) ; break ; case SF_STR_TITLE : psf_binheader_writef (psf, "ems", INAM_MARKER, psf->strings [k].str) ; break ; case SF_STR_COPYRIGHT : psf_binheader_writef (psf, "ems", ICOP_MARKER, psf->strings [k].str) ; break ; case SF_STR_ARTIST : psf_binheader_writef (psf, "ems", IART_MARKER, psf->strings [k].str) ; break ; case SF_STR_COMMENT : psf_binheader_writef (psf, "ems", ICMT_MARKER, psf->strings [k].str) ; break ; case SF_STR_DATE : psf_binheader_writef (psf, "ems", ICRD_MARKER, psf->strings [k].str) ; break ; } ; } ; saved_head_index = psf->headindex ; psf->headindex = prev_head_index ; psf_binheader_writef (psf, "e4", saved_head_index - prev_head_index - 4) ; psf->headindex = saved_head_index ; } /* wav_write_strings */ static int wav_close (SF_PRIVATE *psf) { if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { wav_write_tailer (psf) ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV) wav_write_header (psf, SF_TRUE) ; else wavex_write_header (psf, SF_TRUE) ; } ; return 0 ; } /* wav_close */ static int wav_command (SF_PRIVATE *psf, int command, void *data, int datasize) { /* Avoid compiler warnings. */ psf = psf ; data = data ; datasize = datasize ; switch (command) { default : break ; } ; return 0 ; } /* wav_command */ static int wav_subchunk_parse (SF_PRIVATE *psf, int chunk) { sf_count_t current_pos ; char *cptr ; int dword, bytesread, length ; current_pos = psf_fseek (psf, 0, SEEK_CUR) ; bytesread = psf_binheader_readf (psf, "e4", &length) ; if (current_pos + length > psf->filelength) { psf_log_printf (psf, "%M : %d (should be %d)\n", chunk, length, (int) (psf->filelength - current_pos)) ; length = psf->filelength - current_pos ; } else psf_log_printf (psf, "%M : %d\n", chunk, length) ; while (bytesread < length) { bytesread += psf_binheader_readf (psf, "m", &chunk) ; switch (chunk) { case adtl_MARKER : case INFO_MARKER : /* These markers don't contain anything. */ psf_log_printf (psf, " %M\n", chunk) ; break ; case data_MARKER: psf_log_printf (psf, " %M inside a LIST block??? Backing out.\n", chunk) ; /* Jump back four bytes and return to caller. */ psf_binheader_readf (psf, "j", -4) ; return 0 ; case ISFT_MARKER : case ICOP_MARKER : case IARL_MARKER : case IART_MARKER : case ICMT_MARKER : case ICRD_MARKER : case IENG_MARKER : case INAM_MARKER : case IPRD_MARKER : case ISBJ_MARKER : case ISRC_MARKER : bytesread += psf_binheader_readf (psf, "e4", &dword) ; dword += (dword & 1) ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; bytesread += dword ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %s\n", chunk, cptr) ; break ; case labl_MARKER : { int mark_id ; bytesread += psf_binheader_readf (psf, "e44", &dword, &mark_id) ; dword -= 4 ; dword += (dword & 1) ; if (dword > SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " *** %M : %d (too big)\n", chunk, dword) ; return SFE_INTERNAL ; } ; cptr = (char*) psf->buffer ; psf_binheader_readf (psf, "b", cptr, dword) ; bytesread += dword ; cptr [dword - 1] = 0 ; psf_log_printf (psf, " %M : %d : %s\n", chunk, mark_id, cptr) ; } ; break ; case DISP_MARKER : case ltxt_MARKER : case note_MARKER : bytesread += psf_binheader_readf (psf, "e4", &dword) ; dword += (dword & 1) ; psf_binheader_readf (psf, "j", dword) ; bytesread += dword ; psf_log_printf (psf, " %M : %d\n", chunk, dword) ; break ; default : psf_binheader_readf (psf, "e4", &dword) ; bytesread += sizeof (dword) ; dword += (dword & 1) ; psf_binheader_readf (psf, "j", dword) ; bytesread += dword ; psf_log_printf (psf, " *** %M : %d\n", chunk, dword) ; if (dword > length) return 0 ; break ; } ; switch (chunk) { case ISFT_MARKER : psf_store_string (psf, SF_STR_SOFTWARE, (char*) psf->buffer) ; break ; case ICOP_MARKER : psf_store_string (psf, SF_STR_COPYRIGHT, (char*) psf->buffer) ; break ; case INAM_MARKER : psf_store_string (psf, SF_STR_TITLE, (char*) psf->buffer) ; break ; case IART_MARKER : psf_store_string (psf, SF_STR_ARTIST, (char*) psf->buffer) ; break ; case ICMT_MARKER : psf_store_string (psf, SF_STR_COMMENT, (char*) psf->buffer) ; break ; case ICRD_MARKER : psf_store_string (psf, SF_STR_DATE, (char*) psf->buffer) ; break ; } ; if (psf->logindex >= SIGNED_SIZEOF (psf->logbuffer) - 2) return SFE_LOG_OVERRUN ; } ; current_pos = psf_fseek (psf, 0, SEEK_CUR) - current_pos ; if (current_pos - 4 != length) psf_log_printf (psf, "**** Bad chunk length %d sbould be %D\n", length, current_pos - 4) ; return 0 ; } /* wav_subchunk_parse */ static int wav_read_smpl_chunk (SF_PRIVATE *psf, unsigned int chunklen) { unsigned int bytesread = 0, dword, sampler_data, loop_count ; int k ; chunklen += (chunklen & 1) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Manufacturer : %X\n", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Product : %u\n", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Period : %u nsec\n", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Midi Note : %u\n", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; if (dword != 0) { LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), "%f", (1.0 * 0x80000000) / ((unsigned int) dword)) ; psf_log_printf (psf, " Pitch Fract. : %s\n", (char*) psf->buffer) ; } else psf_log_printf (psf, " Pitch Fract. : 0\n") ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " SMPTE Format : %u\n", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), "%02d:%02d:%02d %02d", (dword >> 24) & 0x7F, (dword >> 16) & 0x7F, (dword >> 8) & 0x7F, dword & 0x7F) ; psf_log_printf (psf, " SMPTE Offset : %s\n", psf->buffer) ; bytesread += psf_binheader_readf (psf, "e4", &loop_count) ; psf_log_printf (psf, " Loop Count : %u\n", loop_count) ; /* Sampler Data holds the number of data bytes after the CUE chunks which ** is not actually CUE data. Display value after CUE data. */ bytesread += psf_binheader_readf (psf, "e4", &sampler_data) ; while (loop_count > 0 && chunklen - bytesread >= 24) { bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Cue ID : %2u", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Type : %2u", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Start : %5u", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " End : %5u", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Fraction : %5u", dword) ; bytesread += psf_binheader_readf (psf, "e4", &dword) ; psf_log_printf (psf, " Count : %5u\n", dword) ; loop_count -- ; } ; if (chunklen - bytesread == 0) { if (sampler_data != 0) psf_log_printf (psf, " Sampler Data : %u (should be 0)\n", sampler_data) ; else psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ; } else { if (sampler_data != chunklen - bytesread) { psf_log_printf (psf, " Sampler Data : %u (should have been %u)\n", sampler_data, chunklen - bytesread) ; sampler_data = chunklen - bytesread ; } else psf_log_printf (psf, " Sampler Data : %u\n", sampler_data) ; psf_log_printf (psf, " ") ; for (k = 0 ; k < (int) sampler_data ; k++) { char ch ; if (k > 0 && (k % 20) == 0) psf_log_printf (psf, "\n ") ; bytesread += psf_binheader_readf (psf, "1", &ch) ; psf_log_printf (psf, "%02X ", ch & 0xFF) ; } ; psf_log_printf (psf, "\n") ; } ; return 0 ; } /* wav_read_smpl_chunk */ /* ** The acid chunk goes a little something like this: ** ** 4 bytes 'acid' ** 4 bytes (int) length of chunk ** 4 bytes (int) ??? ** 2 bytes (short) root note ** 2 bytes (short) ??? ** 4 bytes (float) ??? ** 4 bytes (int) number of beats ** 2 bytes (short) meter denominator ** 2 bytes (short) meter numerator ** 4 bytes (float) tempo ** */ static int wav_read_acid_chunk (SF_PRIVATE *psf, unsigned int chunklen) { unsigned int bytesread = 0 ; int beats ; short rootnote, q1, meter_denom, meter_numer ; float q2, q3, tempo ; chunklen += (chunklen & 1) ; bytesread += psf_binheader_readf (psf, "e224f", &rootnote, &q1, &q2, &q3) ; LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), "%f", q2) ; psf_log_printf (psf, " Root note : %d\n ???? : %d\n ???? : %s\n ???? : %d\n", rootnote, q1, psf->buffer, q3) ; bytesread += psf_binheader_readf (psf, "e422f", &beats, &meter_denom, &meter_numer, &tempo) ; LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), "%f", tempo) ; psf_log_printf (psf, " Beats : %d\n Meter : %d/%d\n Tempo : %s\n", beats, meter_denom, meter_numer, psf->buffer) ; psf_binheader_readf (psf, "j", chunklen - bytesread) ; return 0 ; } /* wav_read_acid_chunk */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 9c551689-a1d8-4905-9f56-26a204374f18 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include /*------------------------------------------------------------------------------ * Private static functions. */ int wav_w64_read_fmt_chunk (SF_PRIVATE *psf, WAV_FMT *wav_fmt, int structsize) { int bytesread, k, bytespersec = 0 ; memset (wav_fmt, 0, sizeof (WAV_FMT)) ; if (structsize < 16) return SFE_WAV_FMT_SHORT ; if (structsize > SIGNED_SIZEOF (WAV_FMT)) return SFE_WAV_FMT_TOO_BIG ; /* Read the minimal WAV file header here. */ bytesread = psf_binheader_readf (psf, "e224422", &(wav_fmt->format), &(wav_fmt->min.channels), &(wav_fmt->min.samplerate), &(wav_fmt->min.bytespersec), &(wav_fmt->min.blockalign), &(wav_fmt->min.bitwidth)) ; psf_log_printf (psf, " Format : 0x%X => %s\n", wav_fmt->format, wav_w64_format_str (wav_fmt->format)) ; psf_log_printf (psf, " Channels : %d\n", wav_fmt->min.channels) ; psf_log_printf (psf, " Sample Rate : %d\n", wav_fmt->min.samplerate) ; psf_log_printf (psf, " Block Align : %d\n", wav_fmt->min.blockalign) ; if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.bitwidth == 24 && wav_fmt->min.blockalign == 4 * wav_fmt->min.channels) { psf_log_printf (psf, "\nInvalid file generated by Syntrillium's Cooledit!\n" "Treating as WAVE_FORMAT_IEEE_FLOAT 32 bit floating point file.\n\n") ; psf_log_printf (psf, " Bit Width : 24 (should be 32)\n") ; wav_fmt->min.bitwidth = 32 ; wav_fmt->format = WAVE_FORMAT_IEEE_FLOAT ; } else if (wav_fmt->format == WAVE_FORMAT_GSM610 && wav_fmt->min.bitwidth != 0) psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; else psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; psf->sf.samplerate = wav_fmt->min.samplerate ; psf->sf.frames = 0 ; /* Correct this when reading data chunk. */ psf->sf.channels = wav_fmt->min.channels ; switch (wav_fmt->format) { case WAVE_FORMAT_PCM : case WAVE_FORMAT_IEEE_FLOAT : bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign ; if (wav_fmt->min.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; psf->bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth) ; break ; case WAVE_FORMAT_ALAW : case WAVE_FORMAT_MULAW : if (wav_fmt->min.bytespersec / wav_fmt->min.blockalign != wav_fmt->min.samplerate) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; psf->bytewidth = 1 ; if (structsize >= 18) { bytesread += psf_binheader_readf (psf, "e2", &(wav_fmt->size20.extrabytes)) ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->size20.extrabytes) ; } ; break ; case WAVE_FORMAT_IMA_ADPCM : if (wav_fmt->min.bitwidth != 4) return SFE_WAV_ADPCM_NOT4BIT ; if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2) return SFE_WAV_ADPCM_CHANNELS ; bytesread += psf_binheader_readf (psf, "e22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ; bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ; if (wav_fmt->ima.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ima.bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ; break ; case WAVE_FORMAT_MS_ADPCM : if (wav_fmt->msadpcm.bitwidth != 4) return SFE_WAV_ADPCM_NOT4BIT ; if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2) return SFE_WAV_ADPCM_CHANNELS ; bytesread += psf_binheader_readf (psf, "e222", &(wav_fmt->msadpcm.extrabytes), &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ; bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ; if (wav_fmt->min.bytespersec == (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; else if (wav_fmt->min.bytespersec == (wav_fmt->min.samplerate / wav_fmt->msadpcm.samplesperblock) * wav_fmt->min.blockalign) psf_log_printf (psf, " Bytes/sec : %d (should be %d (MS BUG!))\n", wav_fmt->min.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->msadpcm.samplesperblock) ; if (wav_fmt->msadpcm.numcoeffs > SIGNED_SIZEOF (MS_ADPCM_WAV_FMT) / SIGNED_SIZEOF (int)) { psf_log_printf (psf, " No. of Coeffs : %d ****\n", wav_fmt->msadpcm.numcoeffs) ; wav_fmt->msadpcm.numcoeffs = SIGNED_SIZEOF (MS_ADPCM_WAV_FMT) / SIGNED_SIZEOF (int) ; } else psf_log_printf (psf, " No. of Coeffs : %d\n", wav_fmt->msadpcm.numcoeffs) ; psf_log_printf (psf, " Index Coeffs1 Coeffs2\n") ; for (k = 0 ; k < wav_fmt->msadpcm.numcoeffs ; k++) { bytesread += psf_binheader_readf (psf, "e22", &(wav_fmt->msadpcm.coeffs [k].coeff1), &(wav_fmt->msadpcm.coeffs [k].coeff2)) ; LSF_SNPRINTF ((char*) psf->buffer, sizeof (psf->buffer), " %2d %7d %7d\n", k, wav_fmt->msadpcm.coeffs [k].coeff1, wav_fmt->msadpcm.coeffs [k].coeff2) ; psf_log_printf (psf, (char*) psf->buffer) ; } ; break ; case WAVE_FORMAT_GSM610 : if (wav_fmt->gsm610.channels != 1 || wav_fmt->gsm610.blockalign != 65) return SFE_WAV_GSM610_FORMAT ; bytesread += psf_binheader_readf (psf, "e22", &(wav_fmt->gsm610.extrabytes), &(wav_fmt->gsm610.samplesperblock)) ; if (wav_fmt->gsm610.samplesperblock != 320) return SFE_WAV_GSM610_FORMAT ; bytespersec = (wav_fmt->gsm610.samplerate * wav_fmt->gsm610.blockalign) / wav_fmt->gsm610.samplesperblock ; if (wav_fmt->gsm610.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->gsm610.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->gsm610.bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->gsm610.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; break ; case WAVE_FORMAT_EXTENSIBLE : if (wav_fmt->ext.bytespersec / wav_fmt->ext.blockalign != wav_fmt->ext.samplerate) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ext.bytespersec) ; bytesread += psf_binheader_readf (psf, "e224", &(wav_fmt->ext.extrabytes), &(wav_fmt->ext.validbits), &(wav_fmt->ext.channelmask)) ; psf_log_printf (psf, " Valid Bits : %d\n", wav_fmt->ext.validbits) ; psf_log_printf (psf, " Channel Mask : 0x%X\n", wav_fmt->ext.channelmask) ; bytesread += psf_binheader_readf (psf, "e422", &(wav_fmt->ext.esf.esf_field1), &(wav_fmt->ext.esf.esf_field2), &(wav_fmt->ext.esf.esf_field3)) ; /* compare the esf_fields with each known GUID? and print?*/ psf_log_printf (psf, " Subformat\n") ; psf_log_printf (psf, " esf_field1 : 0x%X\n", wav_fmt->ext.esf.esf_field1) ; psf_log_printf (psf, " esf_field2 : 0x%X\n", wav_fmt->ext.esf.esf_field2) ; psf_log_printf (psf, " esf_field3 : 0x%X\n", wav_fmt->ext.esf.esf_field3) ; psf_log_printf (psf, " esf_field4 : ") ; for (k = 0 ; k < 8 ; k++) { bytesread += psf_binheader_readf (psf, "1", &(wav_fmt->ext.esf.esf_field4 [k])) ; psf_log_printf (psf, "0x%X ", wav_fmt->ext.esf.esf_field4 [k] & 0xFF) ; } ; psf_log_printf (psf, "\n") ; psf->bytewidth = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ; break ; default : break ; } ; if (bytesread > structsize) { psf_log_printf (psf, "*** wav_w64_read_fmt_chunk (bytesread > structsize)\n") ; return SFE_W64_FMT_SHORT ; } else psf_binheader_readf (psf, "j", structsize - bytesread) ; psf->blockwidth = wav_fmt->min.channels * psf->bytewidth ; return 0 ; } /* wav_w64_read_fmt_chunk */ /*============================================================================== */ typedef struct { int ID ; const char *name ; } WAV_FORMAT_DESC ; #define STR(x) #x #define FORMAT_TYPE(x) { x, STR (x) } static WAV_FORMAT_DESC wave_descs [] = { FORMAT_TYPE (WAVE_FORMAT_PCM), FORMAT_TYPE (WAVE_FORMAT_MS_ADPCM), FORMAT_TYPE (WAVE_FORMAT_IEEE_FLOAT), FORMAT_TYPE (WAVE_FORMAT_VSELP), FORMAT_TYPE (WAVE_FORMAT_IBM_CVSD), FORMAT_TYPE (WAVE_FORMAT_ALAW), FORMAT_TYPE (WAVE_FORMAT_MULAW), FORMAT_TYPE (WAVE_FORMAT_OKI_ADPCM), FORMAT_TYPE (WAVE_FORMAT_IMA_ADPCM), FORMAT_TYPE (WAVE_FORMAT_MEDIASPACE_ADPCM), FORMAT_TYPE (WAVE_FORMAT_SIERRA_ADPCM), FORMAT_TYPE (WAVE_FORMAT_G723_ADPCM), FORMAT_TYPE (WAVE_FORMAT_DIGISTD), FORMAT_TYPE (WAVE_FORMAT_DIGIFIX), FORMAT_TYPE (WAVE_FORMAT_DIALOGIC_OKI_ADPCM), FORMAT_TYPE (WAVE_FORMAT_MEDIAVISION_ADPCM), FORMAT_TYPE (WAVE_FORMAT_CU_CODEC), FORMAT_TYPE (WAVE_FORMAT_YAMAHA_ADPCM), FORMAT_TYPE (WAVE_FORMAT_SONARC), FORMAT_TYPE (WAVE_FORMAT_DSPGROUP_TRUESPEECH), FORMAT_TYPE (WAVE_FORMAT_ECHOSC1), FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF36), FORMAT_TYPE (WAVE_FORMAT_APTX), FORMAT_TYPE (WAVE_FORMAT_AUDIOFILE_AF10), FORMAT_TYPE (WAVE_FORMAT_PROSODY_1612), FORMAT_TYPE (WAVE_FORMAT_LRC), FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC2), FORMAT_TYPE (WAVE_FORMAT_GSM610), FORMAT_TYPE (WAVE_FORMAT_MSNAUDIO), FORMAT_TYPE (WAVE_FORMAT_ANTEX_ADPCME), FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_VQLPC), FORMAT_TYPE (WAVE_FORMAT_DIGIREAL), FORMAT_TYPE (WAVE_FORMAT_DIGIADPCM), FORMAT_TYPE (WAVE_FORMAT_CONTROL_RES_CR10), FORMAT_TYPE (WAVE_FORMAT_NMS_VBXADPCM), FORMAT_TYPE (WAVE_FORMAT_ROLAND_RDAC), FORMAT_TYPE (WAVE_FORMAT_ECHOSC3), FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_ADPCM), FORMAT_TYPE (WAVE_FORMAT_ROCKWELL_DIGITALK), FORMAT_TYPE (WAVE_FORMAT_XEBEC), FORMAT_TYPE (WAVE_FORMAT_G721_ADPCM), FORMAT_TYPE (WAVE_FORMAT_G728_CELP), FORMAT_TYPE (WAVE_FORMAT_MSG723), FORMAT_TYPE (WAVE_FORMAT_MPEG), FORMAT_TYPE (WAVE_FORMAT_RT24), FORMAT_TYPE (WAVE_FORMAT_PAC), FORMAT_TYPE (WAVE_FORMAT_MPEGLAYER3), FORMAT_TYPE (WAVE_FORMAT_LUCENT_G723), FORMAT_TYPE (WAVE_FORMAT_CIRRUS), FORMAT_TYPE (WAVE_FORMAT_ESPCM), FORMAT_TYPE (WAVE_FORMAT_VOXWARE), FORMAT_TYPE (WAVE_FORMAT_CANOPUS_ATRAC), FORMAT_TYPE (WAVE_FORMAT_G726_ADPCM), FORMAT_TYPE (WAVE_FORMAT_G722_ADPCM), FORMAT_TYPE (WAVE_FORMAT_DSAT), FORMAT_TYPE (WAVE_FORMAT_DSAT_DISPLAY), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_BYTE_ALIGNED), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC8), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC10), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC16), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_AC20), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT24), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_RT29HW), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR12), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_VR18), FORMAT_TYPE (WAVE_FORMAT_VOXWARE_TQ40), FORMAT_TYPE (WAVE_FORMAT_SOFTSOUND), FORMAT_TYPE (WAVE_FORMAT_VOXARE_TQ60), FORMAT_TYPE (WAVE_FORMAT_MSRT24), FORMAT_TYPE (WAVE_FORMAT_G729A), FORMAT_TYPE (WAVE_FORMAT_MVI_MV12), FORMAT_TYPE (WAVE_FORMAT_DF_G726), FORMAT_TYPE (WAVE_FORMAT_DF_GSM610), FORMAT_TYPE (WAVE_FORMAT_ONLIVE), FORMAT_TYPE (WAVE_FORMAT_SBC24), FORMAT_TYPE (WAVE_FORMAT_DOLBY_AC3_SPDIF), FORMAT_TYPE (WAVE_FORMAT_ZYXEL_ADPCM), FORMAT_TYPE (WAVE_FORMAT_PHILIPS_LPCBB), FORMAT_TYPE (WAVE_FORMAT_PACKED), FORMAT_TYPE (WAVE_FORMAT_RHETOREX_ADPCM), FORMAT_TYPE (IBM_FORMAT_MULAW), FORMAT_TYPE (IBM_FORMAT_ALAW), FORMAT_TYPE (IBM_FORMAT_ADPCM), FORMAT_TYPE (WAVE_FORMAT_VIVO_G723), FORMAT_TYPE (WAVE_FORMAT_VIVO_SIREN), FORMAT_TYPE (WAVE_FORMAT_DIGITAL_G723), FORMAT_TYPE (WAVE_FORMAT_CREATIVE_ADPCM), FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH8), FORMAT_TYPE (WAVE_FORMAT_CREATIVE_FASTSPEECH10), FORMAT_TYPE (WAVE_FORMAT_QUARTERDECK), FORMAT_TYPE (WAVE_FORMAT_FM_TOWNS_SND), FORMAT_TYPE (WAVE_FORMAT_BZV_DIGITAL), FORMAT_TYPE (WAVE_FORMAT_VME_VMPCM), FORMAT_TYPE (WAVE_FORMAT_OLIGSM), FORMAT_TYPE (WAVE_FORMAT_OLIADPCM), FORMAT_TYPE (WAVE_FORMAT_OLICELP), FORMAT_TYPE (WAVE_FORMAT_OLISBC), FORMAT_TYPE (WAVE_FORMAT_OLIOPR), FORMAT_TYPE (WAVE_FORMAT_LH_CODEC), FORMAT_TYPE (WAVE_FORMAT_NORRIS), FORMAT_TYPE (WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS), FORMAT_TYPE (WAVE_FORMAT_DVM), FORMAT_TYPE (WAVE_FORMAT_INTERWAV_VSC112), FORMAT_TYPE (WAVE_FORMAT_EXTENSIBLE), } ; char const* wav_w64_format_str (int k) { int lower, upper, mid ; lower = -1 ; upper = sizeof (wave_descs) / sizeof (WAV_FORMAT_DESC) ; /* binary search */ if ((wave_descs [0].ID <= k) & (k <= wave_descs [upper - 1].ID)) { while (lower + 1 < upper) { mid = (upper + lower) / 2 ; if (k == wave_descs [mid].ID) return wave_descs [mid].name ; if (k < wave_descs [mid].ID) upper = mid ; else lower = mid ; } ; } ; return "Unknown format" ; } /* wav_w64_format_str */ int wav_w64_srate2blocksize (int srate_chan_product) { if (srate_chan_product < 12000) return 256 ; if (srate_chan_product < 23000) return 512 ; if (srate_chan_product < 44000) return 1024 ; return 2048 ; } /* srate2blocksize */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 43c1b1dd-8abd-43da-a8cd-44da914b64a5 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #if (ENABLE_EXPERIMENTAL_CODE == 0) int wve_open (SF_PRIVATE *psf) { if (psf) return SFE_UNIMPLEMENTED ; return (psf && 0) ; } /* wve_open */ #else #define SFE_WVE_NOT_WVE 666 /*------------------------------------------------------------------------------ ** Macros to handle big/little endian issues. */ #define ALAW_MARKER MAKE_MARKER ('A', 'L', 'a', 'w') #define SOUN_MARKER MAKE_MARKER ('S', 'o', 'u', 'n') #define DFIL_MARKER MAKE_MARKER ('d', 'F', 'i', 'l') /*------------------------------------------------------------------------------ ** Private static functions. */ static int wve_read_header (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------ ** Public function. */ int wve_open (SF_PRIVATE *psf) { int subformat, error = 0 ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) return SFE_UNIMPLEMENTED ; if ((error = wve_read_header (psf))) return error ; if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_WVE) return SFE_BAD_OPEN_FORMAT ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; return error ; } /* wve_open */ /*------------------------------------------------------------------------------ */ static int wve_read_header (SF_PRIVATE *psf) { int marker ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pm", 0, &marker) ; if (marker != ALAW_MARKER) return SFE_WVE_NOT_WVE ; psf_binheader_readf (psf, "m", &marker) ; if (marker != SOUN_MARKER) return SFE_WVE_NOT_WVE ; psf_binheader_readf (psf, "m", &marker) ; if (marker != DFIL_MARKER) return SFE_WVE_NOT_WVE ; psf_log_printf (psf, "Read only : Psion Palmtop Alaw (.wve)\n" " Sample Rate : 8000\n" " Channels : 1\n" " Encoding : A-law\n") ; psf->dataoffset = 0x20 ; psf->datalength = psf->filelength - psf->dataoffset ; psf->sf.format = SF_FORMAT_WVE | SF_FORMAT_ALAW ; psf->sf.samplerate = 8000 ; psf->sf.frames = psf->datalength ; psf->sf.channels = 1 ; return alaw_init (psf) ; } /* wve_read_header */ /*------------------------------------------------------------------------------ */ #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: ba368cb5-523f-45e4-98c1-5b99a102f73f */ /* ** Copyright (C) 2003,2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #define MAX_XI_SAMPLES 16 /*------------------------------------------------------------------------------ ** Private static functions and tyepdefs. */ typedef struct { /* Warning, this filename is NOT nul terminated. */ char filename [22] ; char software [20] ; char sample_name [22] ; int loop_begin, loop_end ; int sample_flags ; /* Data for encoder and decoder. */ short last_16 ; } XI_PRIVATE ; static int xi_close (SF_PRIVATE *psf) ; static int xi_write_header (SF_PRIVATE *psf, int calc_length) ; static int xi_read_header (SF_PRIVATE *psf) ; static int dpcm_init (SF_PRIVATE *psf) ; static sf_count_t dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ; /*------------------------------------------------------------------------------ ** Public function. */ int xi_open (SF_PRIVATE *psf) { XI_PRIVATE *pxi ; int subformat, error = 0 ; if (psf->is_pipe) return SFE_XI_NO_PIPE ; if (psf->fdata) pxi = psf->fdata ; else if ((pxi = calloc (1, sizeof (XI_PRIVATE))) == NULL) return SFE_MALLOC_FAILED ; psf->fdata = pxi ; if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0)) { if ((error = xi_read_header (psf))) return error ; } ; subformat = psf->sf.format & SF_FORMAT_SUBMASK ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_XI) return SFE_BAD_OPEN_FORMAT ; psf->endian = SF_ENDIAN_LITTLE ; psf->sf.channels = 1 ; /* Always mono */ psf->sf.samplerate = 44100 ; /* Always */ /* Set up default instrument and software name. */ memcpy (pxi->filename, "Default Name ", sizeof (pxi->filename)) ; memcpy (pxi->software, PACKAGE "-" VERSION " ", sizeof (pxi->software)) ; memset (pxi->sample_name, 0, sizeof (pxi->sample_name)) ; LSF_SNPRINTF (pxi->sample_name, sizeof (pxi->sample_name), "%s", "Sample #1") ; pxi->sample_flags = (subformat == SF_FORMAT_DPCM_16) ? 16 : 0 ; if (xi_write_header (psf, SF_FALSE)) return psf->error ; psf->write_header = xi_write_header ; } ; psf->close = xi_close ; psf->seek = dpcm_seek ; psf->sf.seekable = SF_FALSE ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; switch (subformat) { case SF_FORMAT_DPCM_8 : /* 8-bit differential PCM. */ case SF_FORMAT_DPCM_16 : /* 16-bit differential PCM. */ error = dpcm_init (psf) ; break ; default : break ; } ; return error ; } /* xi_open */ /*------------------------------------------------------------------------------ */ static int xi_close (SF_PRIVATE *psf) { psf = psf ; return 0 ; } /* xi_close */ /*============================================================================== */ static sf_count_t dpcm_read_dsc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dsc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dsc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dsc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t dpcm_write_s2dsc (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dpcm_write_i2dsc (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dpcm_write_f2dsc (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dpcm_write_d2dsc (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dles2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dles2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dles2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dpcm_read_dles2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static sf_count_t dpcm_write_s2dles (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; static sf_count_t dpcm_write_i2dles (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; static sf_count_t dpcm_write_f2dles (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; static sf_count_t dpcm_write_d2dles (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; static int dpcm_init (SF_PRIVATE *psf) { if (psf->bytewidth == 0 || psf->sf.channels == 0) return SFE_INTERNAL ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; if (psf->mode == SFM_READ || psf->mode == SFM_RDWR) { switch (psf->bytewidth) { case 1 : psf->read_short = dpcm_read_dsc2s ; psf->read_int = dpcm_read_dsc2i ; psf->read_float = dpcm_read_dsc2f ; psf->read_double = dpcm_read_dsc2d ; break ; case 2 : psf->read_short = dpcm_read_dles2s ; psf->read_int = dpcm_read_dles2i ; psf->read_float = dpcm_read_dles2f ; psf->read_double = dpcm_read_dles2d ; break ; default : psf_log_printf (psf, "dpcm_init() returning SFE_UNIMPLEMENTED\n") ; return SFE_UNIMPLEMENTED ; } ; } ; if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR) { switch (psf->bytewidth) { case 1 : psf->write_short = dpcm_write_s2dsc ; psf->write_int = dpcm_write_i2dsc ; psf->write_float = dpcm_write_f2dsc ; psf->write_double = dpcm_write_d2dsc ; break ; case 2 : psf->write_short = dpcm_write_s2dles ; psf->write_int = dpcm_write_i2dles ; psf->write_float = dpcm_write_f2dles ; psf->write_double = dpcm_write_d2dles ; break ; default : psf_log_printf (psf, "dpcm_init() returning SFE_UNIMPLEMENTED\n") ; return SFE_UNIMPLEMENTED ; } ; } ; psf->filelength = psf_get_filelen (psf) ; psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ; psf->sf.frames = psf->datalength / psf->blockwidth ; return 0 ; } /* dpcm_init */ /*============================================================================== */ static sf_count_t dpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) { XI_PRIVATE *pxi ; int total, bufferlen, len ; if ((pxi = psf->fdata) == NULL) return SFE_INTERNAL ; if (psf->datalength < 0 || psf->dataoffset < 0) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (offset == 0) { psf_fseek (psf, psf->dataoffset, SEEK_SET) ; pxi->last_16 = 0 ; return 0 ; } ; if (offset < 0 || offset > psf->sf.frames) { psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; if (mode != SFM_READ) { /* What to do about write??? */ psf->error = SFE_BAD_SEEK ; return ((sf_count_t) -1) ; } ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if ((psf->sf.format & SF_FORMAT_SUBMASK) == SF_FORMAT_DPCM_16) { total = offset ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (total > 0) { len = (total > bufferlen) ? bufferlen : total ; total -= dpcm_read_dles2s (psf, (short *) psf->buffer, len) ; } ; } else { total = offset ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (total > 0) { len = (total > bufferlen) ? bufferlen : total ; total -= dpcm_read_dsc2s (psf, (short *) psf->buffer, len) ; } ; } ; return offset ; } /* dpcm_seek */ static int xi_write_header (SF_PRIVATE *psf, int calc_length) { XI_PRIVATE *pxi ; sf_count_t current ; const char *string ; if ((pxi = psf->fdata) == NULL) return SFE_INTERNAL ; calc_length = calc_length ; /* Avoid a compiler warning. */ current = psf_ftell (psf) ; /* Reset the current header length to zero. */ psf->header [0] = 0 ; psf->headindex = 0 ; psf_fseek (psf, 0, SEEK_SET) ; string = "Extended Instrument: " ; psf_binheader_writef (psf, "b", string, strlen (string)) ; psf_binheader_writef (psf, "b1", pxi->filename, sizeof (pxi->filename), 0x1A) ; /* Write software version and two byte XI version. */ psf_binheader_writef (psf, "eb2", pxi->software, sizeof (pxi->software), (1 << 8) + 2) ; /* ** Jump note numbers (96), volume envelope (48), pan envelope (48), ** volume points (1), pan points (1) */ psf_binheader_writef (psf, "z", (size_t) (96 + 48 + 48 + 1 + 1)) ; /* Jump volume loop (3 bytes), pan loop (3), envelope flags (3), vibrato (3) ** fade out (2), 22 unknown bytes, and then write sample_count (2 bytes). */ psf_binheader_writef (psf, "ez2z2", (size_t) (4 * 3), 0x1234, (size_t) 22, 1) ; psf->sf.frames = 12 ; pxi->loop_begin = 0 ; pxi->loop_end = 0 ; psf_binheader_writef (psf, "et844", psf->sf.frames, pxi->loop_begin, pxi->loop_end) ; /* volume, fine tune, flags, pan, note, namelen */ psf_binheader_writef (psf, "111111", 128, 0, pxi->sample_flags, 128, 0, strlen (pxi->sample_name)) ; psf_binheader_writef (psf, "b", pxi->sample_name, sizeof (pxi->sample_name)) ; /* Header construction complete so write it out. */ psf_fwrite (psf->header, psf->headindex, 1, psf) ; if (psf->error) return psf->error ; psf->dataoffset = psf->headindex ; if (current > 0) psf_fseek (psf, current, SEEK_SET) ; return psf->error ; } /* xi_write_header */ static int xi_read_header (SF_PRIVATE *psf) { char buffer [64], name [32] ; short version, fade_out, sample_count ; int k, loop_begin, loop_end ; int sample_sizes [MAX_XI_SAMPLES] ; psf_binheader_readf (psf, "pb", 0, buffer, 21) ; memset (sample_sizes, 0, sizeof (sample_sizes)) ; buffer [20] = 0 ; if (strcmp (buffer, "Extended Instrument:") != 0) return SFE_XI_BAD_HEADER ; memset (buffer, 0, sizeof (buffer)) ; psf_binheader_readf (psf, "b", buffer, 23) ; if (buffer [22] != 0x1A) return SFE_XI_BAD_HEADER ; buffer [22] = 0 ; psf_log_printf (psf, "Extended Instrument : %s\n", buffer) ; psf_binheader_readf (psf, "be2", buffer, 20, &version) ; buffer [19] = 0 ; psf_log_printf (psf, "Software : %s\nVersion : %d.%02d\n", buffer, version / 256, version % 256) ; /* Jump note numbers (96), volume envelope (48), pan envelope (48), ** volume points (1), pan points (1) */ psf_binheader_readf (psf, "j", 96 + 48 + 48 + 1 + 1) ; psf_binheader_readf (psf, "b", buffer, 12) ; psf_log_printf (psf, "Volume Loop\n sustain : %u\n begin : %u\n end : %u\n", buffer [0], buffer [1], buffer [2]) ; psf_log_printf (psf, "Pan Loop\n sustain : %u\n begin : %u\n end : %u\n", buffer [3], buffer [4], buffer [5]) ; psf_log_printf (psf, "Envelope Flags\n volume : 0x%X\n pan : 0x%X\n", buffer [6] & 0xFF, buffer [7] & 0xFF) ; psf_log_printf (psf, "Vibrato\n type : %u\n sweep : %u\n depth : %u\n rate : %u\n", buffer [8], buffer [9], buffer [10], buffer [11]) ; /* ** Read fade_out then jump reserved (2 bytes) and ???? (20 bytes) and ** sample_count. */ psf_binheader_readf (psf, "e2j2", &fade_out, 2 + 20, &sample_count) ; psf_log_printf (psf, "Fade out : %d\n", fade_out) ; /* XI file can contain up to 16 samples. */ if (sample_count > MAX_XI_SAMPLES) return SFE_XI_EXCESS_SAMPLES ; /* Log all data for each sample. */ for (k = 0 ; k < sample_count ; k++) { psf_binheader_readf (psf, "e444", &(sample_sizes [k]), &loop_begin, &loop_end) ; /* Read 5 know bytes, 1 unknown byte and 22 name bytes. */ psf_binheader_readf (psf, "bb", buffer, 6, name, 22) ; name [21] = 0 ; psf_log_printf (psf, "Sample #%d\n name : %s\n size : %d\n", k + 1, name, sample_sizes [k]) ; psf_log_printf (psf, " loop\n begin : %d\n end : %d\n", loop_begin, loop_end) ; psf_log_printf (psf, " volume : %u\n f. tune : %d\n flags : 0x%02X ", buffer [0] & 0xFF, buffer [1] & 0xFF, buffer [2] & 0xFF) ; psf_log_printf (psf, " (") ; if (buffer [2] & 1) psf_log_printf (psf, " Loop") ; if (buffer [2] & 2) psf_log_printf (psf, " PingPong") ; psf_log_printf (psf, (buffer [2] & 16) ? " 16bit" : " 8bit") ; psf_log_printf (psf, " )\n") ; psf_log_printf (psf, " pan : %u\n note : %d\n namelen : %d\n", buffer [3] & 0xFF, buffer [4], buffer [5]) ; if (k != 0) continue ; if (buffer [2] & 16) { psf->sf.format = SF_FORMAT_XI | SF_FORMAT_DPCM_16 ; psf->bytewidth = 2 ; } else { psf->sf.format = SF_FORMAT_XI | SF_FORMAT_DPCM_8 ; psf->bytewidth = 1 ; } ; } ; while (sample_count > 1 && sample_sizes [sample_count - 1] == 0) sample_count -- ; /* Currently, we can only handle 1 sample per file. */ if (sample_count > 2) { psf_log_printf (psf, "*** Sample count is less than 16 but more than 1.\n") ; psf_log_printf (psf, " sample count : %d sample_sizes [%d] : %d\n", sample_count, sample_count - 1, sample_sizes [sample_count - 1]) ; return SFE_XI_EXCESS_SAMPLES ; } ; psf->dataoffset = psf_fseek (psf, 0, SEEK_CUR) ; psf_log_printf (psf, "Data Offset : %D\n", psf->dataoffset) ; psf->datalength = sample_sizes [0] ; if (psf->dataoffset + psf->datalength > psf->filelength) { psf_log_printf (psf, "*** File seems to be truncated. Should be at least %D bytes long.\n", psf->dataoffset + sample_sizes [0]) ; psf->datalength = psf->filelength - psf->dataoffset ; } ; if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset) return SFE_BAD_SEEK ; psf->close = xi_close ; psf->endian = SF_ENDIAN_LITTLE ; psf->sf.channels = 1 ; /* Always mono */ psf->sf.samplerate = 44100 ; /* Always */ psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* xi_read_header */ /*============================================================================== */ static void dsc2s_array (XI_PRIVATE *pxi, signed char *src, int count, short *dest) ; static void dsc2i_array (XI_PRIVATE *pxi, signed char *src, int count, int *dest) ; static void dsc2f_array (XI_PRIVATE *pxi, signed char *src, int count, float *dest, float normfact) ; static void dsc2d_array (XI_PRIVATE *pxi, signed char *src, int count, double *dest, double normfact) ; static void dles2s_array (XI_PRIVATE *pxi, short *src, int count, short *dest) ; static void dles2i_array (XI_PRIVATE *pxi, short *src, int count, int *dest) ; static void dles2f_array (XI_PRIVATE *pxi, short *src, int count, float *dest, float normfact) ; static void dles2d_array (XI_PRIVATE *pxi, short *src, int count, double *dest, double normfact) ; static sf_count_t dpcm_read_dsc2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; dsc2s_array (pxi, (signed char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dsc2s */ static sf_count_t dpcm_read_dsc2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; dsc2i_array (pxi, (signed char*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dsc2i */ static sf_count_t dpcm_read_dsc2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; dsc2f_array (pxi, (signed char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dsc2f */ static sf_count_t dpcm_read_dsc2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (signed char), readcount, psf) ; dsc2d_array (pxi, (signed char*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dsc2d */ /*------------------------------------------------------------------------------ */ static sf_count_t dpcm_read_dles2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; dles2s_array (pxi, (short*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dles2s */ static sf_count_t dpcm_read_dles2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; dles2i_array (pxi, (short*) (psf->buffer), thisread, ptr + total) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dles2i */ static sf_count_t dpcm_read_dles2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; float normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; dles2f_array (pxi, (short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dles2f */ static sf_count_t dpcm_read_dles2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, readcount, thisread ; sf_count_t total = 0 ; double normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { readcount = (len >= bufferlen) ? bufferlen : (int) len ; thisread = psf_fread (psf->buffer, sizeof (short), readcount, psf) ; dles2d_array (pxi, (short*) (psf->buffer), thisread, ptr + total, normfact) ; total += thisread ; len -= thisread ; if (thisread < readcount) break ; } ; return total ; } /* dpcm_read_dles2d */ /*============================================================================== */ static void s2dsc_array (XI_PRIVATE *pxi, short *src, signed char *dest, int count) ; static void i2dsc_array (XI_PRIVATE *pxi, int *src, signed char *dest, int count) ; static void f2dsc_array (XI_PRIVATE *pxi, float *src, signed char *dest, int count, float normfact) ; static void d2dsc_array (XI_PRIVATE *pxi, double *src, signed char *dest, int count, double normfact) ; static void s2dles_array (XI_PRIVATE *pxi, short *src, short *dest, int count) ; static void i2dles_array (XI_PRIVATE *pxi, int *src, short *dest, int count) ; static void f2dles_array (XI_PRIVATE *pxi, float *src, short *dest, int count, float normfact) ; static void d2dles_array (XI_PRIVATE *pxi, double *src, short *dest, int count, double normfact) ; static sf_count_t dpcm_write_s2dsc (SF_PRIVATE *psf, short *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2dsc_array (pxi, ptr + total, (signed char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_s2dsc */ static sf_count_t dpcm_write_i2dsc (SF_PRIVATE *psf, int *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2dsc_array (pxi, ptr + total, (signed char*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_i2dsc */ static sf_count_t dpcm_write_f2dsc (SF_PRIVATE *psf, float *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; float normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7F) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; f2dsc_array (pxi, ptr + total, (signed char*) (psf->buffer), writecount, normfact) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_f2dsc */ static sf_count_t dpcm_write_d2dsc (SF_PRIVATE *psf, double *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; double normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7F) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (signed char) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; d2dsc_array (pxi, ptr + total, (signed char*) (psf->buffer), writecount, normfact) ; thiswrite = psf_fwrite (psf->buffer, sizeof (signed char), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_d2dsc */ static sf_count_t dpcm_write_s2dles (SF_PRIVATE *psf, short *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; s2dles_array (pxi, ptr + total, (short*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_s2dles */ static sf_count_t dpcm_write_i2dles (SF_PRIVATE *psf, int *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; if ((pxi = psf->fdata) == NULL) return 0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; i2dles_array (pxi, ptr + total, (short*) (psf->buffer), writecount) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_i2dles */ static sf_count_t dpcm_write_f2dles (SF_PRIVATE *psf, float *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; float normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; f2dles_array (pxi, ptr + total, (short*) (psf->buffer), writecount, normfact) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_f2dles */ static sf_count_t dpcm_write_d2dles (SF_PRIVATE *psf, double *ptr, sf_count_t len) { XI_PRIVATE *pxi ; int bufferlen, writecount, thiswrite ; sf_count_t total = 0 ; double normfact ; if ((pxi = psf->fdata) == NULL) return 0 ; normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ; bufferlen = sizeof (psf->buffer) / sizeof (short) ; while (len > 0) { writecount = (len >= bufferlen) ? bufferlen : (int) len ; d2dles_array (pxi, ptr + total, (short*) (psf->buffer), writecount, normfact) ; thiswrite = psf_fwrite (psf->buffer, sizeof (short), writecount, psf) ; total += thiswrite ; len -= thiswrite ; if (thiswrite < writecount) break ; } ; return total ; } /* dpcm_write_d2dles */ /*============================================================================== */ static void dsc2s_array (XI_PRIVATE *pxi, signed char *src, int count, short *dest) { signed char last_val ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { last_val += src [k] ; dest [k] = last_val << 8 ; } ; pxi->last_16 = last_val << 8 ; } /* dsc2s_array */ static void dsc2i_array (XI_PRIVATE *pxi, signed char *src, int count, int *dest) { signed char last_val ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { last_val += src [k] ; dest [k] = last_val << 24 ; } ; pxi->last_16 = last_val << 8 ; } /* dsc2i_array */ static void dsc2f_array (XI_PRIVATE *pxi, signed char *src, int count, float *dest, float normfact) { signed char last_val ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { last_val += src [k] ; dest [k] = last_val * normfact ; } ; pxi->last_16 = last_val << 8 ; } /* dsc2f_array */ static void dsc2d_array (XI_PRIVATE *pxi, signed char *src, int count, double *dest, double normfact) { signed char last_val ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { last_val += src [k] ; dest [k] = last_val * normfact ; } ; pxi->last_16 = last_val << 8 ; } /* dsc2d_array */ /*------------------------------------------------------------------------------ */ static void s2dsc_array (XI_PRIVATE *pxi, short *src, signed char *dest, int count) { signed char last_val, current ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { current = src [k] >> 8 ; dest [k] = current - last_val ; last_val = current ; } ; pxi->last_16 = last_val << 8 ; } /* s2dsc_array */ static void i2dsc_array (XI_PRIVATE *pxi, int *src, signed char *dest, int count) { signed char last_val, current ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { current = src [k] >> 24 ; dest [k] = current - last_val ; last_val = current ; } ; pxi->last_16 = last_val << 8 ; } /* i2dsc_array */ static void f2dsc_array (XI_PRIVATE *pxi, float *src, signed char *dest, int count, float normfact) { signed char last_val, current ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { current = lrintf (src [k] * normfact) ; dest [k] = current - last_val ; last_val = current ; } ; pxi->last_16 = last_val << 8 ; } /* f2dsc_array */ static void d2dsc_array (XI_PRIVATE *pxi, double *src, signed char *dest, int count, double normfact) { signed char last_val, current ; int k ; last_val = pxi->last_16 >> 8 ; for (k = 0 ; k < count ; k++) { current = lrint (src [k] * normfact) ; dest [k] = current - last_val ; last_val = current ; } ; pxi->last_16 = last_val << 8 ; } /* d2dsc_array */ /*============================================================================== */ static void dles2s_array (XI_PRIVATE *pxi, short *src, int count, short *dest) { short last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { last_val += LES2H_SHORT (src [k]) ; dest [k] = last_val ; } ; pxi->last_16 = last_val ; } /* dles2s_array */ static void dles2i_array (XI_PRIVATE *pxi, short *src, int count, int *dest) { short last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { last_val += LES2H_SHORT (src [k]) ; dest [k] = last_val << 16 ; } ; pxi->last_16 = last_val ; } /* dles2i_array */ static void dles2f_array (XI_PRIVATE *pxi, short *src, int count, float *dest, float normfact) { short last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { last_val += LES2H_SHORT (src [k]) ; dest [k] = last_val * normfact ; } ; pxi->last_16 = last_val ; } /* dles2f_array */ static void dles2d_array (XI_PRIVATE *pxi, short *src, int count, double *dest, double normfact) { short last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { last_val += LES2H_SHORT (src [k]) ; dest [k] = last_val * normfact ; } ; pxi->last_16 = last_val ; } /* dles2d_array */ /*------------------------------------------------------------------------------ */ static void s2dles_array (XI_PRIVATE *pxi, short *src, short *dest, int count) { short diff, last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { diff = src [k] - last_val ; dest [k] = LES2H_SHORT (diff) ; last_val = src [k] ; } ; pxi->last_16 = last_val ; } /* s2dles_array */ static void i2dles_array (XI_PRIVATE *pxi, int *src, short *dest, int count) { short diff, last_val ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { diff = (src [k] >> 16) - last_val ; dest [k] = LES2H_SHORT (diff) ; last_val = src [k] >> 16 ; } ; pxi->last_16 = last_val ; } /* i2dles_array */ static void f2dles_array (XI_PRIVATE *pxi, float *src, short *dest, int count, float normfact) { short diff, last_val, current ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { current = lrintf (src [k] * normfact) ; diff = current - last_val ; dest [k] = LES2H_SHORT (diff) ; last_val = current ; } ; pxi->last_16 = last_val ; } /* f2dles_array */ static void d2dles_array (XI_PRIVATE *pxi, double *src, short *dest, int count, double normfact) { short diff, last_val, current ; int k ; last_val = pxi->last_16 ; for (k = 0 ; k < count ; k++) { current = lrint (src [k] * normfact) ; diff = current - last_val ; dest [k] = LES2H_SHORT (diff) ; last_val = current ; } ; pxi->last_16 = last_val ; } /* d2dles_array */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 1ab2dbe0-29af-4d80-9c6f-cb21b67521bc */ chuck-1.2.0.8.dfsg/src/util_sndfile.h0000644000175000017500000026413410600421720015770 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ /* ** libsndfile Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ //----------------------------------------------------------------------------- // name: util_sndfile.h // desc: libsndfile for ChucK // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // Ari Lazier (alazier@alumni.princeton.edu) // libsndfile: Erik de Castro Lopo (erikd@mega-nerd.com) //----------------------------------------------------------------------------- #ifndef __UTIL_SNDFILE_H__ #define __UTIL_SNDFILE_H__ #include #include // XXX philipd this might break things? // these defines were placed after the machine-dependent // checks below...i'm not sure why #define COMPILER_IS_GCC 1 #define CPU_CLIPS_NEGATIVE 1 #define ENABLE_EXPERIMENTAL_CODE 0 #define GCC_MAJOR_VERSION 3 #define HAVE_CALLOC 1 #define HAVE_CEIL 1 #define HAVE_DECL_S_IRGRP 1 #define HAVE_DLFCN_H 1 #define HAVE_FLEXIBLE_ARRAY 1 #define HAVE_FLOOR 1 #define HAVE_FMOD 1 #define HAVE_FREE 1 #define HAVE_FSTAT 1 #define HAVE_FSYNC 1 #define HAVE_FTRUNCATE 1 #define HAVE_GETPAGESIZE 1 #define HAVE_GMTIME 1 #define HAVE_GMTIME_R 1 #define HAVE_INTTYPES_H 1 #define HAVE_LIBM 1 #define HAVE_LSEEK 1 #define HAVE_MALLOC 1 #define HAVE_MEMORY_H 1 #define HAVE_MMAP 1 #define HAVE_OPEN 1 #define HAVE_READ 1 #define HAVE_REALLOC 1 #define HAVE_SNPRINTF 1 #define HAVE_STDINT_H 1 #define HAVE_STDLIB_H 1 #define HAVE_STRINGS_H 1 #define HAVE_STRING_H 1 #define HAVE_SYS_STAT_H 1 #define HAVE_SYS_TYPES_H 1 #define HAVE_SYS_WAIT_H 1 #define HAVE_VSNPRINTF 1 #define HAVE_WRITE 1 #define PACKAGE "libsndfile" #define PACKAGE_BUGREPORT "erikd@mega-nerd.com" #define PACKAGE_NAME "libsndfile" #define PACKAGE_STRING "libsndfile 1.0.10" #define PACKAGE_TARNAME "libsndfile" #define PACKAGE_VERSION "1.0.10" #define SIZEOF_DOUBLE 8 #define SIZEOF_FLOAT 4 #define SIZEOF_INT 4 #define SIZEOF_LONG 4 #define SIZEOF_OFF_T 8 #define SIZEOF_SF_COUNT_T 8 #define SIZEOF_SHORT 2 #define SIZEOF_SIZE_T 4 #define SIZEOF_SSIZE_T 4 #define SIZEOF_VOIDP 4 #define STDC_HEADERS 1 #define VERSION "1.0.10" #ifdef __MACOSX_CORE__ #define CPU_CLIPS_POSITIVE 1 #ifdef __LITTLE_ENDIAN__ #define CPU_IS_BIG_ENDIAN 0 #define CPU_IS_LITTLE_ENDIAN 1 #define HAVE_LRINTF 1 #define HAVE_LRINT 1 #else #define CPU_IS_BIG_ENDIAN 1 #define CPU_IS_LITTLE_ENDIAN 0 #endif #define HAVE_PREAD 1 #define HAVE_PWRITE 1 #define OS_IS_MACOSX 1 #define OS_IS_WIN32 0 #define TYPEOF_SF_COUNT_T off_t #endif #if defined(__PLATFORM_WIN32__) //Dev Studio #define CPU_CLIPS_POSITIVE 0 #define CPU_IS_BIG_ENDIAN 0 #define CPU_IS_LITTLE_ENDIAN 1 #define HAVE_LRINTF 0 #define HAVE_LRINT 0 #undef HAVE_GMTIME_R #undef HAVE_GMTIME #undef HAVE_SNPRINTF #undef HAVE_FLEXIBLE_ARRAY #define OS_IS_MACOSX 0 #define OS_IS_WIN32 1 #define TYPEOF_SF_COUNT_T off_t #endif #if defined (__WINDOWS_PTHREAD__) //Cygwin #define CPU_CLIPS_POSITIVE 0 #define CPU_IS_BIG_ENDIAN 0 #define CPU_IS_LITTLE_ENDIAN 1 #define HAVE_LRINTF 0 #define HAVE_LRINT 0 #define OS_IS_MACOSX 0 #define OS_IS_WIN32 0 #define TYPEOF_SF_COUNT_T off_t #endif #ifdef __LINUX_ALSA__ #define HAVE_ALSA_ASOUNDLIB_H #endif #if defined(__LINUX_ALSA__) || defined(__LINUX_OSS__) || defined(__LINUX_JACK__) #define CPU_CLIPS_POSITIVE 0 #define CPU_IS_BIG_ENDIAN 0 #define CPU_IS_LITTLE_ENDIAN 1 #define HAVE_PREAD 1 #define HAVE_PWRITE 1 #define OS_IS_MACOSX 0 #define OS_IS_WIN32 0 #define SIZEOF_OFF64_T 0 #define SIZEOF_LOFF_T 8 #define TYPEOF_SF_COUNT_T loff_t #define _FILE_OFFSET_BITS 64 #define HAVE_FDATASYNC 1 #define HAVE_ENDIAN_H 1 #define HAVE_LRINTF 1 #define HAVE_LRINT 1 #endif // XXX 'inline' is necessary for C compilation // in the microsoft vc6 compiler... // and other ms win32 specialteez. #ifdef __PLATFORM_WIN32__ #define C_INLINE __inline #define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFF #else #define C_INLINE inline #define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL #define HAVE_UNISTD_H 1 #define HAVE_SSIZE_T 1 #endif /* ** sndfile.h -- system-wide definitions ** ** API documentation is in the doc/ directory of the source code tarball ** and at http://www.mega-nerd.com/libsndfile/api.html. */ #ifndef SNDFILE_H #define SNDFILE_H /* This is the version 1.0.X header file. */ #define SNDFILE_1 /* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */ #if (defined (__MWERKS__)) #else #include #endif #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* The following file types can be read and written. ** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise ** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and ** SF_FORMAT_SUBMASK can be used to separate the major and minor file ** types. */ enum { /* Major formats. */ SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian). */ SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ SF_FORMAT_VOC = 0x080000, /* VOC files. */ SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ /* Subtypes from here on. */ SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ /* Endian-ness options. */ SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ SF_FORMAT_SUBMASK = 0x0000FFFF, SF_FORMAT_TYPEMASK = 0x0FFF0000, SF_FORMAT_ENDMASK = 0x30000000 } ; /* ** The following are the valid command numbers for the sf_command() ** interface. The use of these commands is documented in the file ** command.html in the doc directory of the source code distribution. */ enum { SFC_GET_LIB_VERSION = 0x1000, SFC_GET_LOG_INFO = 0x1001, SFC_GET_NORM_DOUBLE = 0x1010, SFC_GET_NORM_FLOAT = 0x1011, SFC_SET_NORM_DOUBLE = 0x1012, SFC_SET_NORM_FLOAT = 0x1013, SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, SFC_GET_SIMPLE_FORMAT = 0x1021, SFC_GET_FORMAT_INFO = 0x1028, SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, SFC_GET_FORMAT_MAJOR = 0x1031, SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, SFC_GET_FORMAT_SUBTYPE = 0x1033, SFC_CALC_SIGNAL_MAX = 0x1040, SFC_CALC_NORM_SIGNAL_MAX = 0x1041, SFC_CALC_MAX_ALL_CHANNELS = 0x1042, SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, SFC_SET_ADD_PEAK_CHUNK = 0x1050, SFC_UPDATE_HEADER_NOW = 0x1060, SFC_SET_UPDATE_HEADER_AUTO = 0x1061, SFC_FILE_TRUNCATE = 0x1080, SFC_SET_RAW_START_OFFSET = 0x1090, SFC_SET_DITHER_ON_WRITE = 0x10A0, SFC_SET_DITHER_ON_READ = 0x10A1, SFC_GET_DITHER_INFO_COUNT = 0x10A2, SFC_GET_DITHER_INFO = 0x10A3, SFC_GET_EMBED_FILE_INFO = 0x10B0, SFC_SET_CLIPPING = 0x10C0, SFC_GET_CLIPPING = 0x10C1, SFC_GET_INSTRUMENT = 0x10D0, SFC_SET_INSTRUMENT = 0x10D1, /* Following commands for testing only. */ SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, /* ** SFC_SET_ADD_* values are deprecated and will disappear at some ** time in the future. They are guaranteed to be here up to and ** including version 1.0.8 to avoid breakage of existng software. ** They currently do nothing and will continue to do nothing. */ SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, SFC_SET_ADD_DITHER_ON_READ = 0x1071 } ; /* ** String types that can be set and read from files. Not all file types ** support this and even the file types which support one, may not support ** all string types. */ enum { SF_STR_TITLE = 0x01, SF_STR_COPYRIGHT = 0x02, SF_STR_SOFTWARE = 0x03, SF_STR_ARTIST = 0x04, SF_STR_COMMENT = 0x05, SF_STR_DATE = 0x06 } ; enum { /* True and false */ SF_FALSE = 0, SF_TRUE = 1, /* Modes for opening files. */ SFM_READ = 0x10, SFM_WRITE = 0x20, SFM_RDWR = 0x30 } ; /* Pubic error values. These are guaranteed to remain unchanged for the duration ** of the library major version number. ** There are also a large number of private error numbers which are internal to ** the library which can change at any time. */ enum { SF_ERR_NO_ERROR = 0, SF_ERR_UNRECOGNISED_FORMAT = 1, SF_ERR_SYSTEM = 2 } ; /* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ typedef struct SNDFILE_tag SNDFILE ; /* The following typedef is system specific and is defined when libsndfile is. ** compiled. sf_count_t can be one of loff_t (Linux), off_t (*BSD), ** off64_t (Solaris), __int64_t (Win32) etc. */ typedef TYPEOF_SF_COUNT_T sf_count_t ; //#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL /* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in. ** On write, the SF_INFO structure is filled in by the user and passed into ** sf_open_write (). */ struct SF_INFO { sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ int samplerate ; int channels ; int format ; int sections ; int seekable ; } ; typedef struct SF_INFO SF_INFO ; /* The SF_FORMAT_INFO struct is used to retrieve information about the sound ** file formats libsndfile supports using the sf_command () interface. ** ** Using this interface will allow applications to support new file formats ** and encoding types when libsndfile is upgraded, without requiring ** re-compilation of the application. ** ** Please consult the libsndfile documentation (particularly the information ** on the sf_command () interface) for examples of its use. */ typedef struct { int format ; const char *name ; const char *extension ; } SF_FORMAT_INFO ; /* ** Enums and typedefs for adding dither on read and write. ** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE ** and SFC_SET_DITHER_ON_READ. */ enum { SFD_DEFAULT_LEVEL = 0, SFD_CUSTOM_LEVEL = 0x40000000, SFD_NO_DITHER = 500, SFD_WHITE = 501, SFD_TRIANGULAR_PDF = 502 } ; typedef struct { int type ; double level ; const char *name ; } SF_DITHER_INFO ; /* Struct used to retrieve information about a file embedded within a ** larger file. See SFC_GET_EMBED_FILE_INFO. */ typedef struct { sf_count_t offset ; sf_count_t length ; } SF_EMBED_FILE_INFO ; /* Struct used to retrieve music sample information from a file. */ typedef struct { int basenote ; int gain ; int sustain_mode ; int sustain_start, sustain_end ; int release_mode ; int release_start, reslease_end ; } SF_INSTRUMENT ; /* sustain_mode and release_mode will be one of the following. */ enum { SF_LOOP_NONE = 800, SF_LOOP_FORWARD, SF_LOOP_BACKWARD } ; /* Open the specified file for read, write or both. On error, this will ** return a NULL pointer. To find the error number, pass a NULL SNDFILE ** to sf_perror () or sf_error_str (). ** All calls to sf_open() should be matched with a call to sf_close(). */ SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; /* Use the existing file descriptor to create a SNDFILE object. If close_desc ** is TRUE, the file descriptor will be closed when sf_close() is called. If ** it is FALSE, the descritor will not be closed. ** When passed a descriptor like this, the library will assume that the start ** of file header is at the current file offset. This allows sound files within ** larger container files to be read and/or written. ** On error, this will return a NULL pointer. To find the error number, pass a ** NULL SNDFILE to sf_perror () or sf_error_str (). ** All calls to sf_open_fd() should be matched with a call to sf_close(). */ SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; /* sf_error () returns a error number which can be translated to a text ** string using sf_error_number(). */ int sf_error (SNDFILE *sndfile) ; /* sf_strerror () returns to the caller a pointer to the current error message for ** the given SNDFILE. */ const char* sf_strerror (SNDFILE *sndfile) ; /* sf_error_number () allows the retrieval of the error string for each internal ** error number. ** */ const char* sf_error_number (int errnum) ; /* The following three error functions are deprecated but they will remain in the ** library for the forseeable future. The function sf_strerror() should be used ** in their place. */ int sf_perror (SNDFILE *sndfile) ; int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; /* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ int sf_format_check (const SF_INFO *info) ; /* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses ** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as ** stdio.h function fseek (). ** An offset of zero with whence set to SEEK_SET will position the ** read / write pointer to the first data sample. ** On success sf_seek returns the current position in (multi-channel) ** samples from the start of the file. ** Please see the libsndfile documentation for moving the read pointer ** separately from the write pointer on files open in mode SFM_RDWR. ** On error all of these functions return -1. */ sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; /* Functions for retrieving and setting string data within sound files. ** Not all file types support this features; AIFF and WAV do. For both ** functions, the str_type parameter must be one of the SF_STR_* values ** defined above. ** On error, sf_set_string() returns non-zero while sf_get_string() ** returns NULL. */ int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; const char* sf_get_string (SNDFILE *sndfile, int str_type) ; /* Functions for reading/writing the waveform data of a sound file. */ sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; sf_count_t sf_write_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; /* Functions for reading and writing the data chunk in terms of frames. ** The number of items actually read/written = frames * number of channels. ** sf_xxxx_raw read/writes the raw data bytes from/to the file ** sf_xxxx_short passes data in the native short format ** sf_xxxx_int passes data in the native int format ** sf_xxxx_float passes data in the native float format ** sf_xxxx_double passes data in the native double format ** All of these read/write function return number of frames read/written. */ sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; sf_count_t sf_writef_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; sf_count_t sf_writef_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; sf_count_t sf_writef_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; sf_count_t sf_writef_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; /* Functions for reading and writing the data chunk in terms of items. ** Otherwise similar to above. ** All of these read/write function return number of items read/written. */ sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; sf_count_t sf_write_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; sf_count_t sf_write_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; sf_count_t sf_write_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; sf_count_t sf_write_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; /* Close the SNDFILE and clean up all memory allocations associated with this ** file. ** Returns 0 on success, or an error number. */ int sf_close (SNDFILE *sndfile) ; #ifdef __cplusplus } /* extern "C" */ #endif /* __cplusplus */ #endif /* SNDFILE_H */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef COMMON_H_INCLUDED #define COMMON_H_INCLUDED #ifndef SNDFILE_H #endif #define SF_BUFFER_LEN (8192*2) #define SF_FILENAME_LEN (256) #define SF_HEADER_LEN (4096) #define SF_TEXT_LEN (1024) #define SF_SYSERR_LEN (256) #define SF_MAX_STRINGS (16) #define SF_SEEK_ERROR ((sf_count_t) -1) #define BITWIDTH2BYTES(x) (((x) + 7) / 8) /* For some reason sizeof returns an unsigned value which causes ** a warning when that value is added or subtracted from a signed ** value. Use SIGNED_SIZEOF instead. */ #define SIGNED_SIZEOF(x) ((int) sizeof (x)) #define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0]))) #define SF_MAX(a,b) ((a) > (b) ? (a) : (b)) #define SF_MIN(a,b) ((a) < (b) ? (a) : (b)) enum { /* PEAK chunk location. */ SF_PEAK_START = 42, SF_PEAK_END = 43, /* PEAK chunk location. */ SF_SCALE_MAX = 52, SF_SCALE_MIN = 53, /* str_flags values. */ SF_STR_ALLOW_START = 0x0100, SF_STR_ALLOW_END = 0x0200, /* Location of strings. */ SF_STR_LOCATE_START = 0x0400, SF_STR_LOCATE_END = 0x0800, SFD_TYPEMASK = 0x0FFFFFFF } ; #define SFM_MASK (SFM_READ | SFM_WRITE | SFM_RDWR) #define SFM_UNMASK (~SFM_MASK) /*--------------------------------------------------------------------------------------- ** Formats that may be supported at some time in the future. ** When support is finalised, these values move to src/sndfile.h. */ enum { /* Work in progress. */ /* Formats supported read only. */ SF_FORMAT_WVE = 0x4020000, /* Psion ALaw Sound File */ SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */ SF_FORMAT_DWD = 0x4040000, /* DiamondWare Digirized */ /* Following are detected but not supported. */ SF_FORMAT_OGG = 0x4090000, SF_FORMAT_REX = 0x40A0000, /* Propellorheads Rex/Rcy */ SF_FORMAT_SD2 = 0x40C0000, /* Sound Designer 2 */ SF_FORMAT_REX2 = 0x40D0000, /* Propellorheads Rex2 */ SF_FORMAT_KRZ = 0x40E0000, /* Kurzweil sampler file */ SF_FORMAT_WMA = 0x4100000, /* Windows Media Audio. */ SF_FORMAT_SHN = 0x4110000, /* Shorten. */ SF_FORMAT_FLAC = 0x4120000, /* Unsupported encodings. */ SF_FORMAT_VORBIS = 0x1001, SF_FORMAT_SVX_FIB = 0x1020, /* SVX Fibonacci Delta encoding. */ SF_FORMAT_SVX_EXP = 0x1021, /* SVX Exponential Delta encoding. */ SF_FORMAT_PCM_N = 0x1030 } ; /*--------------------------------------------------------------------------------------- ** PEAK_CHUNK_OLD - This chunk type is common to both AIFF and WAVE files although their ** endian encodings are different. */ typedef struct { float value ; /* signed value of peak */ unsigned int position ; /* the sample frame for the peak */ } PEAK_POS ; typedef struct { unsigned int version ; /* version of the PEAK chunk */ unsigned int timestamp ; /* secs since 1/1/1970 */ #if HAVE_FLEXIBLE_ARRAY PEAK_POS peaks [] ; /* the per channel peak info */ #else PEAK_POS peaks [1] ; /* the per channel peak info */ #endif } PEAK_CHUNK ; typedef struct { int type ; int flags ; char *str ; } STR_DATA ; /*======================================================================================= ** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the ** sf_open_XXXX functions. The caller however has no knowledge of the struct's ** contents. */ typedef struct sf_private_tag { /* Force the compiler to double align the start of buffer. */ double buffer [SF_BUFFER_LEN / sizeof (double)] ; char filename [SF_FILENAME_LEN] ; char syserr [SF_SYSERR_LEN] ; /* logbuffer and logindex should only be changed within the logging functions ** of common.c */ char logbuffer [SF_BUFFER_LEN] ; unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */ int rwf_endian ; /* Header endian-ness flag. */ /* Storage and housekeeping data for adding/reading strings from ** sound files. */ STR_DATA strings [SF_MAX_STRINGS] ; char str_storage [SF_BUFFER_LEN] ; char *str_end ; int str_flags ; /* Guard value. If this changes the buffers above have overflowed. */ int Magick ; /* Index variables for maintaining logbuffer and header above. */ int logindex ; int headindex, headend ; int has_text ; int do_not_close_descriptor ; int filedes ; int end_of_file ; int error ; int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */ int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */ int float_endswap ; /* Need to endswap float32s? */ /* Vairables for handling pipes. */ int is_pipe ; /* True if file is a pipe. */ sf_count_t pipeoffset ; /* Number of bytes read from a pipe. */ /* True if clipping must be performed on float->int conversions. */ int add_clipping ; SF_INFO sf ; int have_written ; /* Has a single write been done to the file? */ int has_peak ; /* Has a PEAK chunk (AIFF and WAVE) been read? */ int peak_loc ; /* Write a PEAK chunk at the start or end of the file? */ PEAK_CHUNK *pchunk ; sf_count_t filelength ; /* Overall length of (embedded) file. */ sf_count_t fileoffset ; /* Offset in number of bytes from beginning of file. */ sf_count_t dataoffset ; /* Offset in number of bytes from beginning of file. */ sf_count_t datalength ; /* Length in bytes of the audio data. */ sf_count_t dataend ; /* Offset to file tailer. */ int blockwidth ; /* Size in bytes of one set of interleaved samples. */ int bytewidth ; /* Size in bytes of one sample (one channel). */ void *dither ; void *interleave ; int last_op ; /* Last operation; either SFM_READ or SFM_WRITE */ sf_count_t read_current ; sf_count_t write_current ; void *fdata ; /* This is a pointer to dynamically allocated file format ** specific data. */ SF_DITHER_INFO write_dither ; SF_DITHER_INFO read_dither ; int norm_double ; int norm_float ; int auto_header ; int ieee_replace ; /* A set of file specific function pointers */ sf_count_t (*read_short) (struct sf_private_tag*, short *ptr, sf_count_t len) ; sf_count_t (*read_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ; sf_count_t (*read_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ; sf_count_t (*read_double) (struct sf_private_tag*, double *ptr, sf_count_t len) ; sf_count_t (*write_short) (struct sf_private_tag*, short *ptr, sf_count_t len) ; sf_count_t (*write_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ; sf_count_t (*write_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ; sf_count_t (*write_double) (struct sf_private_tag*, double *ptr, sf_count_t len) ; sf_count_t (*seek) (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ; int (*write_header) (struct sf_private_tag*, int calc_length) ; int (*command) (struct sf_private_tag*, int command, void *data, int datasize) ; int (*close) (struct sf_private_tag*) ; char *format_desc ; } SF_PRIVATE ; enum { SFE_NO_ERROR = SF_ERR_NO_ERROR, SFE_BAD_OPEN_FORMAT = SF_ERR_UNRECOGNISED_FORMAT, SFE_SYSTEM = SF_ERR_SYSTEM, SFE_BAD_FILE, SFE_BAD_FILE_READ, SFE_OPEN_FAILED, SFE_BAD_SNDFILE_PTR, SFE_BAD_SF_INFO_PTR, SFE_BAD_SF_INCOMPLETE, SFE_BAD_FILE_PTR, SFE_BAD_INT_PTR, SFE_BAD_STAT_SIZE, SFE_MALLOC_FAILED, SFE_UNIMPLEMENTED, SFE_BAD_READ_ALIGN, SFE_BAD_WRITE_ALIGN, SFE_UNKNOWN_FORMAT, SFE_NOT_READMODE, SFE_NOT_WRITEMODE, SFE_BAD_MODE_RW, SFE_BAD_SF_INFO, SFE_BAD_OFFSET, SFE_NO_EMBED_SUPPORT, SFE_NO_EMBEDDED_RDWR, SFE_NO_PIPE_WRITE, SFE_INTERNAL, SFE_LOG_OVERRUN, SFE_BAD_CONTROL_CMD, SFE_BAD_ENDIAN, SFE_CHANNEL_COUNT, SFE_BAD_RDWR_FORMAT, SFE_INTERLEAVE_MODE, SFE_INTERLEAVE_SEEK, SFE_INTERLEAVE_READ, SFE_BAD_SEEK, SFE_NOT_SEEKABLE, SFE_AMBIGUOUS_SEEK, SFE_WRONG_SEEK, SFE_SEEK_FAILED, SFE_BAD_OPEN_MODE, SFE_OPEN_PIPE_RDWR, SFE_RDWR_POSITION, SFE_STR_NO_SUPPORT, SFE_STR_MAX_DATA, SFE_STR_MAX_COUNT, SFE_STR_BAD_TYPE, SFE_STR_NO_ADD_END, SFE_STR_BAD_STRING, SFE_STR_WEIRD, SFE_RDWR_BAD_HEADER, SFE_WAV_NO_RIFF, SFE_WAV_NO_WAVE, SFE_WAV_NO_FMT, SFE_WAV_FMT_SHORT, SFE_WAV_FMT_TOO_BIG, SFE_WAV_BAD_FACT, SFE_WAV_BAD_PEAK, SFE_WAV_PEAK_B4_FMT, SFE_WAV_BAD_FORMAT, SFE_WAV_BAD_BLOCKALIGN, SFE_WAV_NO_DATA, SFE_WAV_ADPCM_NOT4BIT, SFE_WAV_ADPCM_CHANNELS, SFE_WAV_GSM610_FORMAT, SFE_WAV_UNKNOWN_CHUNK, SFE_WAV_WVPK_DATA, SFE_AIFF_NO_FORM, SFE_AIFF_AIFF_NO_FORM, SFE_AIFF_COMM_NO_FORM, SFE_AIFF_SSND_NO_COMM, SFE_AIFF_UNKNOWN_CHUNK, SFE_AIFF_COMM_CHUNK_SIZE, SFE_AIFF_BAD_COMM_CHUNK, SFE_AIFF_PEAK_B4_COMM, SFE_AIFF_BAD_PEAK, SFE_AIFF_NO_SSND, SFE_AIFF_NO_DATA, SFE_AIFF_RW_SSND_NOT_LAST, SFE_AU_UNKNOWN_FORMAT, SFE_AU_NO_DOTSND, SFE_AU_EMBED_BAD_LEN, SFE_RAW_READ_BAD_SPEC, SFE_RAW_BAD_BITWIDTH, SFE_RAW_BAD_FORMAT, SFE_PAF_NO_MARKER, SFE_PAF_VERSION, SFE_PAF_UNKNOWN_FORMAT, SFE_PAF_SHORT_HEADER, SFE_SVX_NO_FORM, SFE_SVX_NO_BODY, SFE_SVX_NO_DATA, SFE_SVX_BAD_COMP, SFE_SVX_BAD_NAME_LENGTH, SFE_NIST_BAD_HEADER, SFE_NIST_CRLF_CONVERISON, SFE_NIST_BAD_ENCODING, SFE_VOC_NO_CREATIVE, SFE_VOC_BAD_FORMAT, SFE_VOC_BAD_VERSION, SFE_VOC_BAD_MARKER, SFE_VOC_BAD_SECTIONS, SFE_VOC_MULTI_SAMPLERATE, SFE_VOC_MULTI_SECTION, SFE_VOC_MULTI_PARAM, SFE_VOC_SECTION_COUNT, SFE_VOC_NO_PIPE, SFE_IRCAM_NO_MARKER, SFE_IRCAM_BAD_CHANNELS, SFE_IRCAM_UNKNOWN_FORMAT, SFE_W64_64_BIT, SFE_W64_NO_RIFF, SFE_W64_NO_WAVE, SFE_W64_NO_FMT, SFE_W64_NO_DATA, SFE_W64_FMT_SHORT, SFE_W64_FMT_TOO_BIG, SFE_W64_ADPCM_NOT4BIT, SFE_W64_ADPCM_CHANNELS, SFE_W64_GSM610_FORMAT, SFE_MAT4_BAD_NAME, SFE_MAT4_NO_SAMPLERATE, SFE_MAT4_ZERO_CHANNELS, SFE_MAT5_BAD_ENDIAN, SFE_MAT5_NO_BLOCK, SFE_MAT5_SAMPLE_RATE, SFE_MAT5_ZERO_CHANNELS, SFE_PVF_NO_PVF1, SFE_PVF_BAD_HEADER, SFE_PVF_BAD_BITWIDTH, SFE_DWVW_BAD_BITWIDTH, SFE_G72X_NOT_MONO, SFE_XI_BAD_HEADER, SFE_XI_EXCESS_SAMPLES, SFE_XI_NO_PIPE, SFE_HTK_NO_PIPE, SFE_SDS_NOT_SDS, SFE_SDS_BAD_BIT_WIDTH, SFE_MAX_ERROR /* This must be last in list. */ } ; int subformat_to_bytewidth (int format) ; int s_bitwidth_to_subformat (int bits) ; int u_bitwidth_to_subformat (int bits) ; /* Functions for reading and writing floats and doubles on processors ** with non-IEEE floats/doubles. */ float float32_be_read (unsigned char *cptr) ; float float32_le_read (unsigned char *cptr) ; void float32_be_write (float in, unsigned char *out) ; void float32_le_write (float in, unsigned char *out) ; double double64_be_read (unsigned char *cptr) ; double double64_le_read (unsigned char *cptr) ; void double64_be_write (double in, unsigned char *out) ; void double64_le_write (double in, unsigned char *out) ; /* Functions for writing to the internal logging buffer. */ void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) ; void psf_log_SF_INFO (SF_PRIVATE *psf) ; void psf_hexdump (void *ptr, int len) ; /* Functions used when writing file headers. */ int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) ; void psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) ; /* Functions used when reading file headers. */ int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) ; /* Functions used in the write function for updating the peak chunk. */ void peak_update_short (SF_PRIVATE *psf, short *ptr, size_t items) ; void peak_update_int (SF_PRIVATE *psf, int *ptr, size_t items) ; void peak_update_double (SF_PRIVATE *psf, double *ptr, size_t items) ; /* Functions defined in command.c. */ int psf_get_format_simple_count (void) ; int psf_get_format_simple (SF_FORMAT_INFO *data) ; int psf_get_format_info (SF_FORMAT_INFO *data) ; int psf_get_format_major_count (void) ; int psf_get_format_major (SF_FORMAT_INFO *data) ; int psf_get_format_subtype_count (void) ; int psf_get_format_subtype (SF_FORMAT_INFO *data) ; void psf_generate_format_desc (SF_PRIVATE *psf) ; double psf_calc_signal_max (SF_PRIVATE *psf, int normalize) ; int psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) ; /* Functions in strings.c. */ const char* psf_get_string (SF_PRIVATE *psf, int str_type) ; int psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) ; /* Default seek function. Use for PCM and float encoded data. */ sf_count_t psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) ; /* Generate the currebt date as a string. */ void psf_get_date_str (char *str, int maxlen) ; int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) ; /*------------------------------------------------------------------------------------ ** File I/O functions which will allow access to large files (> 2 Gig) on ** some 32 bit OSes. Implementation in file_io.c. */ int psf_fopen (SF_PRIVATE *psf, const char *pathname, int flags) ; int psf_set_stdio (SF_PRIVATE *psf, int mode) ; int psf_filedes_valid (SF_PRIVATE *psf) ; void psf_set_file (SF_PRIVATE *psf, int fd) ; sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) ; sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ; sf_count_t psf_fwrite (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ; sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) ; sf_count_t psf_ftell (SF_PRIVATE *psf) ; sf_count_t psf_get_filelen (SF_PRIVATE *psf) ; int psf_is_pipe (SF_PRIVATE *psf) ; int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) ; int psf_fclose (SF_PRIVATE *psf) ; /* void psf_fclearerr (SF_PRIVATE *psf) ; int psf_ferror (SF_PRIVATE *psf) ; */ /*------------------------------------------------------------------------------------ ** Functions for reading and writing different file formats. */ int aiff_open (SF_PRIVATE *psf) ; int au_open (SF_PRIVATE *psf) ; int au_nh_open (SF_PRIVATE *psf) ; /* Headerless version of AU. */ int avr_open (SF_PRIVATE *psf) ; int htk_open (SF_PRIVATE *psf) ; int ircam_open (SF_PRIVATE *psf) ; int mat4_open (SF_PRIVATE *psf) ; int mat5_open (SF_PRIVATE *psf) ; int nist_open (SF_PRIVATE *psf) ; int paf_open (SF_PRIVATE *psf) ; int pvf_open (SF_PRIVATE *psf) ; int raw_open (SF_PRIVATE *psf) ; int sds_open (SF_PRIVATE *psf) ; int svx_open (SF_PRIVATE *psf) ; int voc_open (SF_PRIVATE *psf) ; int w64_open (SF_PRIVATE *psf) ; int wav_open (SF_PRIVATE *psf) ; int xi_open (SF_PRIVATE *psf) ; /* In progress. Do not currently work. */ int ogg_open (SF_PRIVATE *psf) ; int rx2_open (SF_PRIVATE *psf) ; int sd2_open (SF_PRIVATE *psf) ; int txw_open (SF_PRIVATE *psf) ; int wve_open (SF_PRIVATE *psf) ; int dwd_open (SF_PRIVATE *psf) ; int macbinary3_open (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------------ ** Init functions for a number of common data encodings. */ int pcm_init (SF_PRIVATE *psf) ; int ulaw_init (SF_PRIVATE *psf) ; int alaw_init (SF_PRIVATE *psf) ; int float32_init (SF_PRIVATE *psf) ; int double64_init (SF_PRIVATE *psf) ; int dwvw_init (SF_PRIVATE *psf, int bitwidth) ; int gsm610_init (SF_PRIVATE *psf) ; int vox_adpcm_init (SF_PRIVATE *psf) ; int dither_init (SF_PRIVATE *psf, int mode) ; int wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; int wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; int aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ; int interleave_init (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------------ ** Other helper functions. */ void *psf_memset (void *s, int c, sf_count_t n) ; /*------------------------------------------------------------------------------------ ** Here's how we fix systems which don't snprintf / vsnprintf. ** Systems without these functions should use the */ #if (defined (WIN32) || defined (_WIN32)) #define LSF_SNPRINTF _snprintf #define snprintf _snprintf //XXX really? #elif (HAVE_SNPRINTF && ! FORCE_MISSING_SNPRINTF) #define LSF_SNPRINTF snprintf #else int missing_snprintf (char *str, size_t n, char const *fmt, ...) ; #define LSF_SNPRINTF missing_snprintf #endif #if (defined (WIN32) || defined (_WIN32)) #define LSF_VSNPRINTF _vsnprintf #elif (HAVE_VSNPRINTF && ! FORCE_MISSING_SNPRINTF) #define LSF_VSNPRINTF vsnprintf #else int missing_vsnprintf (char *str, size_t n, const char *fmt, ...) ; #define LSF_VSNPRINTF missing_vsnprintf #endif #endif /* COMMON_H_INCLUDED */ /*------------------------------------------------------------------------------------ ** Extra commands for sf_command(). Not for public use yet. */ enum { SFC_TEST_AIFF_ADD_INST_CHUNK = 0x2000, SFC_TEST_WAV_ADD_INFO_CHUNK = 0x2010 } ; /* ** Maybe, one day, make these functions or something like them, public. ** ** Buffer to buffer dithering. Pointer in and out are allowed to point ** to the same buffer for in-place dithering. */ #if 0 int sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int count) ; int sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int count) ; int sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int count) ; int sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ; #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 7b45c0ee-5835-4a18-a4ef-994e4cd95b67 */ /* ** Copyright (C) 1999-2001 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** This file is not the same as the original file from Sun Microsystems. Nearly ** all the original definitions and function prototypes that were in the file ** of this name have been moved to private.h. */ #ifndef G72X_HEADER_FILE #define G72X_HEADER_FILE /* ** Number of samples per block to process. ** Must be a common multiple of possible bits per sample : 2, 3, 4, 5 and 8. */ #define G72x_BLOCK_SIZE (3*5*8) /* ** Identifiers for the differing kinds of G72x ADPCM codecs. ** The identifiers also define the number of encoded bits per sample. */ enum { G723_16_BITS_PER_SAMPLE = 2, G723_24_BITS_PER_SAMPLE = 3, G723_40_BITS_PER_SAMPLE = 5, G721_32_BITS_PER_SAMPLE = 4, G721_40_BITS_PER_SAMPLE = 5, G723_16_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, G723_24_SAMPLES_PER_BLOCK = G723_24_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_24_BITS_PER_SAMPLE), G723_40_SAMPLES_PER_BLOCK = G723_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_40_BITS_PER_SAMPLE), G721_32_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, G721_40_SAMPLES_PER_BLOCK = G721_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G721_40_BITS_PER_SAMPLE), G723_16_BYTES_PER_BLOCK = (G723_16_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G723_24_BYTES_PER_BLOCK = (G723_24_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G723_40_BYTES_PER_BLOCK = (G723_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G721_32_BYTES_PER_BLOCK = (G721_32_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G721_40_BYTES_PER_BLOCK = (G721_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8 } ; /* ** This is the public structure for passing data between the caller and ** the G72x encoder and decoder. ** The private array is used by the encoder and decoder for internal ** state information and should not be changed in any way by the caller. ** When decoding or encoding a stream, the same instance of this struct ** should be used for every call so that the decoder/encoder keeps the ** correct state data between calls. */ typedef struct { /* Private data. Don't mess with it. */ unsigned long sprivateo [256 / sizeof (long)] ; /* Public data. Read only. */ int blocksize, max_bytes, samplesperblock, bytesperblock ; /* Public data. Read and write. */ int blocks, blockcount, samplecount ; unsigned char block [G72x_BLOCK_SIZE] ; short samples [G72x_BLOCK_SIZE] ; } G72x_DATA ; /* External function definitions. */ int g72x_reader_init (G72x_DATA *data, int codec) ; int g72x_writer_init (G72x_DATA *data, int codec) ; /* ** Initialize the ADPCM state table for the given codec. ** Return 0 on success, 1 on fail. */ int g72x_decode_block (G72x_DATA *data) ; /* ** The caller fills data->block with data->bytes bytes before calling the ** function. The value data->bytes must be an integer multiple of ** data->blocksize and be <= data->max_bytes. ** When it returns, the caller can read out data->samples samples. */ int g72x_encode_block (G72x_DATA *data) ; /* ** The caller fills state->samples some integer multiple data->samples_per_block ** (up to G72x_BLOCK_SIZE) samples before calling the function. ** When it returns, the caller can read out bytes encoded bytes. */ #endif /* !G72X_HEADER_FILE */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 6ca84e5f-f932-4ba1-87ee-37056d921621 */ /* * This source code is a product of Sun Microsystems, Inc. and is provided * for unrestricted use. Users may copy or modify this source code without * charge. * * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun source code is provided with no support and without any obligation on * the part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #ifndef G72X_PRIVATE_H #define G72X_PRIVATE_H /* ** The following is the definition of the state structure used by the ** G.721/G.723 encoder and decoder to preserve their internal state ** between successive calls. The meanings of the majority of the state ** structure fields are explained in detail in the CCITT Recommendation ** G.721. The field names are essentially identical to variable names ** in the bit level description of the coding algorithm included in this ** Recommendation. */ typedef struct private_g72x { long yl; /* Locked or steady state step size multiplier. */ short yu; /* Unlocked or non-steady state step size multiplier. */ short dms; /* Short term energy estimate. */ short dml; /* Long term energy estimate. */ short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ short a[2]; /* Coefficients of pole portion of prediction filter. */ short b[6]; /* Coefficients of zero portion of prediction filter. */ short pk[2]; /* ** Signs of previous two samples of a partially ** reconstructed signal. **/ short dq[6]; /* ** Previous 6 samples of the quantized difference ** signal represented in an internal floating point ** format. **/ short sr[2]; /* ** Previous 2 samples of the quantized difference ** signal represented in an internal floating point ** format. */ char td; /* delayed tone detect, new in 1988 version */ /* The following struct members were added for libsndfile. The original ** code worked by calling a set of functions on a sample by sample basis ** which is slow on architectures like Intel x86. For libsndfile, this ** was changed so that the encoding and decoding routines could work on ** a block of samples at a time to reduce the function call overhead. */ int (*encoder) (int, struct private_g72x* state) ; int (*decoder) (int, struct private_g72x* state) ; int codec_bits ; int byte_index, sample_index ; } G72x_STATE ; int predictor_zero (G72x_STATE *state_ptr); int predictor_pole (G72x_STATE *state_ptr); int step_size (G72x_STATE *state_ptr); int quantize (int d, int y, short *table, int size); int reconstruct (int sign, int dqln, int y); void update (int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G72x_STATE *state_ptr); int g721_encoder (int sample, G72x_STATE *state_ptr); int g721_decoder (int code, G72x_STATE *state_ptr); int g723_16_encoder (int sample, G72x_STATE *state_ptr); int g723_16_decoder (int code, G72x_STATE *state_ptr); int g723_24_encoder (int sample, G72x_STATE *state_ptr); int g723_24_decoder (int code, G72x_STATE *state_ptr); int g723_40_encoder (int sample, G72x_STATE *state_ptr); int g723_40_decoder (int code, G72x_STATE *state_ptr); int unpack_bytes (G72x_DATA *data, int bits) ; int pack_bytes (G72x_DATA *data, int bits) ; void private_init_state (G72x_STATE *state_ptr) ; #endif /* G72X_PRIVATE_H */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: d9ad4da7-0fa3-471d-8020-720b5cfb5e5b */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a ** marker indicating different sections of the file. ** The following MAKE_MARKER macro allows th creation of integer constants ** for these markers. */ #if (CPU_IS_LITTLE_ENDIAN == 1) #define MAKE_MARKER(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24)) #elif (CPU_IS_BIG_ENDIAN == 1) #define MAKE_MARKER(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d)) #else #error "Target CPU endian-ness unknown. May need to hand edit src/config.h" #endif /* wo standard endswap macros. */ #define ENDSWAP_SHORT(x) ((((x)>>8)&0xFF)+(((x)&0xFF)<<8)) #define ENDSWAP_INT(x) ((((x)>>24)&0xFF)+(((x)>>8)&0xFF00)+(((x)&0xFF00)<<8)+(((x)&0xFF)<<24)) /* ** Macros to handle reading of data of a specific endian-ness into host endian ** shorts and ints. The single input is an unsigned char* pointer to the start ** of the object. There are two versions of each macro as we need to deal with ** both big and little endian CPUs. */ #if (CPU_IS_LITTLE_ENDIAN == 1) #define LES2H_SHORT(x) (x) #define LEI2H_INT(x) (x) #define BES2H_SHORT(x) ENDSWAP_SHORT(x) #define BEI2H_INT(x) ENDSWAP_INT(x) #elif (CPU_IS_BIG_ENDIAN == 1) #define LES2H_SHORT(x) ENDSWAP_SHORT(x) #define LEI2H_INT(x) ENDSWAP_INT(x) #define BES2H_SHORT(x) (x) #define BEI2H_INT(x) (x) #else #error "Target CPU endian-ness unknown. May need to hand edit src/config.h" #endif #define LES2H_SHORT_PTR(x) ((x) [0] + ((x) [1] << 8)) #define LES2H_INT_PTR(x) (((x) [0] << 16) + ((x) [1] << 24)) #define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8)) #define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24)) #define LEI2H_SHORT_PTR(x) ((x) [2] + ((x) [3] << 8)) #define LEI2H_INT_PTR(x) ((x) [0] + ((x) [1] << 8) + ((x) [2] << 16) + ((x) [3] << 24)) #define BES2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1]) #define BES2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16)) #define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1]) #define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8)) #define BEI2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1]) #define BEI2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8) + (x) [3]) /* Endian swapping routines implemented in sfendian.c. */ void endswap_short_array (short *ptr, int len) ; void endswap_int_array (int *ptr, int len) ; /* Always swaps 8 byte values whether sizeof (long) == 8 or not. */ void endswap_long_array (long *ptr, int len) ; void endswap_short_copy (short *dest, short *src, int len) ; void endswap_int_copy (int *dest, int *src, int len) ; /* Always swaps 8 byte values whether sizeof (long) == 8 or not. */ void endswap_long_copy (long *dest, long *src, int len) ; /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: f0c5cd54-42d3-4237-90ec-11fe24995de7 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #ifndef GSM_H #define GSM_H /* * Interface */ typedef struct gsm_state * gsm; typedef short gsm_signal; /* signed 16 bit */ typedef unsigned char gsm_byte; typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */ #define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */ #define GSM_PATCHLEVEL 10 #define GSM_MINOR 0 #define GSM_MAJOR 1 #define GSM_OPT_VERBOSE 1 #define GSM_OPT_FAST 2 #define GSM_OPT_LTP_CUT 3 #define GSM_OPT_WAV49 4 #define GSM_OPT_FRAME_INDEX 5 #define GSM_OPT_FRAME_CHAIN 6 gsm gsm_create (void); /* Added for libsndfile : May 6, 2002 */ void gsm_init (gsm); void gsm_destroy (gsm); int gsm_print (FILE *, gsm, gsm_byte *); int gsm_option (gsm, int, int *); void gsm_encode (gsm, gsm_signal *, gsm_byte *); int gsm_decode (gsm, gsm_byte *, gsm_signal *); int gsm_explode (gsm, gsm_byte *, gsm_signal *); void gsm_implode (gsm, gsm_signal *, gsm_byte *); #endif /* GSM_H */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 8cfc7698-5433-4b6f-aeca-967c6fda4dec */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef AU_HEADER_FILE #define AU_HEADER_FILE enum { AU_H_G721_32 = 200, AU_H_G723_24 = 201, AU_H_G723_40 = 202 } ; int au_g72x_reader_init (SF_PRIVATE *psf, int codec) ; int au_g72x_writer_init (SF_PRIVATE *psf, int codec) ; #endif /* AU_HEADER_FILE */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 63affc81-e204-4468-9705-60abe4d10689 */ /* ** Copyright (C) 1999-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* This file contains definitions commong to WAV and W64 files. */ #ifndef WAV_W64_H_INCLUDED #define WAV_W64_H_INCLUDED /*------------------------------------------------------------------------------ ** List of known WAV format tags */ enum { /* keep sorted for wav_w64_format_str() */ WAVE_FORMAT_UNKNOWN = 0x0000, /* Microsoft Corporation */ WAVE_FORMAT_PCM = 0x0001, /* Microsoft PCM format */ WAVE_FORMAT_MS_ADPCM = 0x0002, /* Microsoft ADPCM */ WAVE_FORMAT_IEEE_FLOAT = 0x0003, /* Micrososft 32 bit float format */ WAVE_FORMAT_VSELP = 0x0004, /* Compaq Computer Corporation */ WAVE_FORMAT_IBM_CVSD = 0x0005, /* IBM Corporation */ WAVE_FORMAT_ALAW = 0x0006, /* Microsoft Corporation */ WAVE_FORMAT_MULAW = 0x0007, /* Microsoft Corporation */ WAVE_FORMAT_OKI_ADPCM = 0x0010, /* OKI */ WAVE_FORMAT_IMA_ADPCM = 0x0011, /* Intel Corporation */ WAVE_FORMAT_MEDIASPACE_ADPCM = 0x0012, /* Videologic */ WAVE_FORMAT_SIERRA_ADPCM = 0x0013, /* Sierra Semiconductor Corp */ WAVE_FORMAT_G723_ADPCM = 0x0014, /* Antex Electronics Corporation */ WAVE_FORMAT_DIGISTD = 0x0015, /* DSP Solutions, Inc. */ WAVE_FORMAT_DIGIFIX = 0x0016, /* DSP Solutions, Inc. */ WAVE_FORMAT_DIALOGIC_OKI_ADPCM = 0x0017, /* Dialogic Corporation */ WAVE_FORMAT_MEDIAVISION_ADPCM = 0x0018, /* Media Vision, Inc. */ WAVE_FORMAT_CU_CODEC = 0x0019, /* Hewlett-Packard Company */ WAVE_FORMAT_YAMAHA_ADPCM = 0x0020, /* Yamaha Corporation of America */ WAVE_FORMAT_SONARC = 0x0021, /* Speech Compression */ WAVE_FORMAT_DSPGROUP_TRUESPEECH = 0x0022, /* DSP Group, Inc */ WAVE_FORMAT_ECHOSC1 = 0x0023, /* Echo Speech Corporation */ WAVE_FORMAT_AUDIOFILE_AF36 = 0x0024, /* Audiofile, Inc. */ WAVE_FORMAT_APTX = 0x0025, /* Audio Processing Technology */ WAVE_FORMAT_AUDIOFILE_AF10 = 0x0026, /* Audiofile, Inc. */ WAVE_FORMAT_PROSODY_1612 = 0x0027, /* Aculab plc */ WAVE_FORMAT_LRC = 0x0028, /* Merging Technologies S.A. */ WAVE_FORMAT_DOLBY_AC2 = 0x0030, /* Dolby Laboratories */ WAVE_FORMAT_GSM610 = 0x0031, /* Microsoft Corporation */ WAVE_FORMAT_MSNAUDIO = 0x0032, /* Microsoft Corporation */ WAVE_FORMAT_ANTEX_ADPCME = 0x0033, /* Antex Electronics Corporation */ WAVE_FORMAT_CONTROL_RES_VQLPC = 0x0034, /* Control Resources Limited */ WAVE_FORMAT_DIGIREAL = 0x0035, /* DSP Solutions, Inc. */ WAVE_FORMAT_DIGIADPCM = 0x0036, /* DSP Solutions, Inc. */ WAVE_FORMAT_CONTROL_RES_CR10 = 0x0037, /* Control Resources Limited */ WAVE_FORMAT_NMS_VBXADPCM = 0x0038, /* Natural MicroSystems */ WAVE_FORMAT_ROLAND_RDAC = 0x0039, /* Roland */ WAVE_FORMAT_ECHOSC3 = 0x003A, /* Echo Speech Corporation */ WAVE_FORMAT_ROCKWELL_ADPCM = 0x003B, /* Rockwell International */ WAVE_FORMAT_ROCKWELL_DIGITALK = 0x003C, /* Rockwell International */ WAVE_FORMAT_XEBEC = 0x003D, /* Xebec Multimedia Solutions Limited */ WAVE_FORMAT_G721_ADPCM = 0x0040, /* Antex Electronics Corporation */ WAVE_FORMAT_G728_CELP = 0x0041, /* Antex Electronics Corporation */ WAVE_FORMAT_MSG723 = 0x0042, /* Microsoft Corporation */ WAVE_FORMAT_MPEG = 0x0050, /* Microsoft Corporation */ WAVE_FORMAT_RT24 = 0x0052, /* InSoft Inc. */ WAVE_FORMAT_PAC = 0x0053, /* InSoft Inc. */ WAVE_FORMAT_MPEGLAYER3 = 0x0055, /* MPEG 3 Layer 1 */ WAVE_FORMAT_LUCENT_G723 = 0x0059, /* Lucent Technologies */ WAVE_FORMAT_CIRRUS = 0x0060, /* Cirrus Logic */ WAVE_FORMAT_ESPCM = 0x0061, /* ESS Technology */ WAVE_FORMAT_VOXWARE = 0x0062, /* Voxware Inc */ WAVE_FORMAT_CANOPUS_ATRAC = 0x0063, /* Canopus, Co., Ltd. */ WAVE_FORMAT_G726_ADPCM = 0x0064, /* APICOM */ WAVE_FORMAT_G722_ADPCM = 0x0065, /* APICOM */ WAVE_FORMAT_DSAT = 0x0066, /* Microsoft Corporation */ WAVE_FORMAT_DSAT_DISPLAY = 0x0067, /* Microsoft Corporation */ WAVE_FORMAT_VOXWARE_BYTE_ALIGNED = 0x0069, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_AC8 = 0x0070, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_AC10 = 0x0071, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_AC16 = 0x0072, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_AC20 = 0x0073, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_RT24 = 0x0074, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_RT29 = 0x0075, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_RT29HW = 0x0076, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_VR12 = 0x0077, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_VR18 = 0x0078, /* Voxware Inc. */ WAVE_FORMAT_VOXWARE_TQ40 = 0x0079, /* Voxware Inc. */ WAVE_FORMAT_SOFTSOUND = 0x0080, /* Softsound, Ltd. */ WAVE_FORMAT_VOXARE_TQ60 = 0x0081, /* Voxware Inc. */ WAVE_FORMAT_MSRT24 = 0x0082, /* Microsoft Corporation */ WAVE_FORMAT_G729A = 0x0083, /* AT&T Laboratories */ WAVE_FORMAT_MVI_MV12 = 0x0084, /* Motion Pixels */ WAVE_FORMAT_DF_G726 = 0x0085, /* DataFusion Systems (Pty) (Ltd) */ WAVE_FORMAT_DF_GSM610 = 0x0086, /* DataFusion Systems (Pty) (Ltd) */ /* removed because duplicate */ /* WAVE_FORMAT_ISIAUDIO = 0x0088, */ /* Iterated Systems, Inc. */ WAVE_FORMAT_ONLIVE = 0x0089, /* OnLive! Technologies, Inc. */ WAVE_FORMAT_SBC24 = 0x0091, /* Siemens Business Communications Systems */ WAVE_FORMAT_DOLBY_AC3_SPDIF = 0x0092, /* Sonic Foundry */ WAVE_FORMAT_ZYXEL_ADPCM = 0x0097, /* ZyXEL Communications, Inc. */ WAVE_FORMAT_PHILIPS_LPCBB = 0x0098, /* Philips Speech Processing */ WAVE_FORMAT_PACKED = 0x0099, /* Studer Professional Audio AG */ WAVE_FORMAT_RHETOREX_ADPCM = 0x0100, /* Rhetorex, Inc. */ /* removed because of the following */ /* WAVE_FORMAT_IRAT = 0x0101,*/ /* BeCubed Software Inc. */ /* these three are unofficial */ IBM_FORMAT_MULAW = 0x0101, /* IBM mu-law format */ IBM_FORMAT_ALAW = 0x0102, /* IBM a-law format */ IBM_FORMAT_ADPCM = 0x0103, /* IBM AVC Adaptive Differential PCM format */ WAVE_FORMAT_VIVO_G723 = 0x0111, /* Vivo Software */ WAVE_FORMAT_VIVO_SIREN = 0x0112, /* Vivo Software */ WAVE_FORMAT_DIGITAL_G723 = 0x0123, /* Digital Equipment Corporation */ WAVE_FORMAT_CREATIVE_ADPCM = 0x0200, /* Creative Labs, Inc */ WAVE_FORMAT_CREATIVE_FASTSPEECH8 = 0x0202, /* Creative Labs, Inc */ WAVE_FORMAT_CREATIVE_FASTSPEECH10 = 0x0203, /* Creative Labs, Inc */ WAVE_FORMAT_QUARTERDECK = 0x0220, /* Quarterdeck Corporation */ WAVE_FORMAT_FM_TOWNS_SND = 0x0300, /* Fujitsu Corporation */ WAVE_FORMAT_BZV_DIGITAL = 0x0400, /* Brooktree Corporation */ WAVE_FORMAT_VME_VMPCM = 0x0680, /* AT&T Labs, Inc. */ WAVE_FORMAT_OLIGSM = 0x1000, /* Ing C. Olivetti & C., S.p.A. */ WAVE_FORMAT_OLIADPCM = 0x1001, /* Ing C. Olivetti & C., S.p.A. */ WAVE_FORMAT_OLICELP = 0x1002, /* Ing C. Olivetti & C., S.p.A. */ WAVE_FORMAT_OLISBC = 0x1003, /* Ing C. Olivetti & C., S.p.A. */ WAVE_FORMAT_OLIOPR = 0x1004, /* Ing C. Olivetti & C., S.p.A. */ WAVE_FORMAT_LH_CODEC = 0x1100, /* Lernout & Hauspie */ WAVE_FORMAT_NORRIS = 0x1400, /* Norris Communications, Inc. */ /* removed because duplicate */ /* WAVE_FORMAT_ISIAUDIO = 0x1401, */ /* AT&T Labs, Inc. */ WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS = 0x1500, /* AT&T Labs, Inc. */ WAVE_FORMAT_DVM = 0x2000, /* FAST Multimedia AG */ WAVE_FORMAT_INTERWAV_VSC112 = 0x7150, /* ????? */ WAVE_FORMAT_EXTENSIBLE = 0xFFFE } ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; } MIN_WAV_FMT ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short dummy ; } WAV_FMT_SIZE20 ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short samplesperblock ; unsigned short numcoeffs ; struct { short coeff1 ; short coeff2 ; } coeffs [7] ; } MS_ADPCM_WAV_FMT ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short samplesperblock ; } IMA_ADPCM_WAV_FMT ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short auxblocksize ; } G72x_ADPCM_WAV_FMT ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short samplesperblock ; } GSM610_WAV_FMT ; typedef struct { unsigned int esf_field1 ; unsigned short esf_field2 ; unsigned short esf_field3 ; char esf_field4 [8] ; } EXT_SUBFORMAT ; typedef struct { unsigned short format ; unsigned short channels ; unsigned int samplerate ; unsigned int bytespersec ; unsigned short blockalign ; unsigned short bitwidth ; unsigned short extrabytes ; unsigned short validbits ; unsigned int channelmask ; EXT_SUBFORMAT esf ; } EXTENSIBLE_WAV_FMT ; typedef union { unsigned short format ; MIN_WAV_FMT min ; IMA_ADPCM_WAV_FMT ima ; MS_ADPCM_WAV_FMT msadpcm ; G72x_ADPCM_WAV_FMT g72x ; EXTENSIBLE_WAV_FMT ext ; GSM610_WAV_FMT gsm610 ; WAV_FMT_SIZE20 size20 ; char padding [512] ; } WAV_FMT ; typedef struct { int frames ; } FACT_CHUNK ; #define WAV_W64_GSM610_BLOCKSIZE 65 #define WAV_W64_GSM610_SAMPLES 320 /*------------------------------------------------------------------------------------ ** Functions defined in wav_ms_adpcm.c */ #define MSADPCM_ADAPT_COEFF_COUNT 7 void msadpcm_write_adapt_coeffs (SF_PRIVATE *psf) ; /*------------------------------------------------------------------------------------ ** Functions defined in wav_gsm610.c */ int wav_w64_srate2blocksize (int srate_chan_product) ; char const* wav_w64_format_str (int k) ; int wav_w64_read_fmt_chunk (SF_PRIVATE *psf, WAV_FMT *wav_fmt, int structsize) ; #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 877fde12-9be3-4a31-8a5a-fdae39958613 */ /* ** Copyright (C) 1999-2001 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* ** This file is not the same as the original file from Sun Microsystems. Nearly ** all the original definitions and function prototypes that were in the file ** of this name have been moved to private.h. */ #ifndef G72X_HEADER_FILE #define G72X_HEADER_FILE /* ** Number of samples per block to process. ** Must be a common multiple of possible bits per sample : 2, 3, 4, 5 and 8. */ #define G72x_BLOCK_SIZE (3*5*8) /* ** Identifiers for the differing kinds of G72x ADPCM codecs. ** The identifiers also define the number of encoded bits per sample. */ enum { G723_16_BITS_PER_SAMPLE = 2, G723_24_BITS_PER_SAMPLE = 3, G723_40_BITS_PER_SAMPLE = 5, G721_32_BITS_PER_SAMPLE = 4, G721_40_BITS_PER_SAMPLE = 5, G723_16_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, G723_24_SAMPLES_PER_BLOCK = G723_24_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_24_BITS_PER_SAMPLE), G723_40_SAMPLES_PER_BLOCK = G723_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_40_BITS_PER_SAMPLE), G721_32_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE, G721_40_SAMPLES_PER_BLOCK = G721_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G721_40_BITS_PER_SAMPLE), G723_16_BYTES_PER_BLOCK = (G723_16_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G723_24_BYTES_PER_BLOCK = (G723_24_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G723_40_BYTES_PER_BLOCK = (G723_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G721_32_BYTES_PER_BLOCK = (G721_32_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8, G721_40_BYTES_PER_BLOCK = (G721_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8 } ; /* ** This is the public structure for passing data between the caller and ** the G72x encoder and decoder. ** The private array is used by the encoder and decoder for internal ** state information and should not be changed in any way by the caller. ** When decoding or encoding a stream, the same instance of this struct ** should be used for every call so that the decoder/encoder keeps the ** correct state data between calls. */ typedef struct { /* Private data. Don't mess with it. */ unsigned long sprivateo [256 / sizeof (long)] ; /* Public data. Read only. */ int blocksize, max_bytes, samplesperblock, bytesperblock ; /* Public data. Read and write. */ int blocks, blockcount, samplecount ; unsigned char block [G72x_BLOCK_SIZE] ; short samples [G72x_BLOCK_SIZE] ; } G72x_DATA ; /* External function definitions. */ int g72x_reader_init (G72x_DATA *data, int codec) ; int g72x_writer_init (G72x_DATA *data, int codec) ; /* ** Initialize the ADPCM state table for the given codec. ** Return 0 on success, 1 on fail. */ int g72x_decode_block (G72x_DATA *data) ; /* ** The caller fills data->block with data->bytes bytes before calling the ** function. The value data->bytes must be an integer multiple of ** data->blocksize and be <= data->max_bytes. ** When it returns, the caller can read out data->samples samples. */ int g72x_encode_block (G72x_DATA *data) ; /* ** The caller fills state->samples some integer multiple data->samples_per_block ** (up to G72x_BLOCK_SIZE) samples before calling the function. ** When it returns, the caller can read out bytes encoded bytes. */ #endif /* !G72X_HEADER_FILE */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 6ca84e5f-f932-4ba1-87ee-37056d921621 */ /* * Copyright 1992 by Jutta Degener and Carsten Bormann, Technische * Universitaet Berlin. See the accompanying file "COPYRIGHT" for * details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE. */ #ifndef PRIVATE_H #define PRIVATE_H /* Added by Erik de Castro Lopo */ #define USE_FLOAT_MUL #define FAST #define WAV49 /* Added by Erik de Castro Lopo */ typedef short word; /* 16 bit signed int */ typedef int longword; /* 32 bit signed int */ typedef unsigned short uword; /* unsigned word */ typedef unsigned int ulongword; /* unsigned longword */ struct gsm_state { word dp0[ 280 ] ; word z1; /* preprocessing.c, Offset_com. */ longword L_z2; /* Offset_com. */ int mp; /* Preemphasis */ word u[8] ; /* short_term_aly_filter.c */ word LARpp[2][8] ; /* */ word j; /* */ word ltp_cut; /* long_term.c, LTP crosscorr. */ word nrp; /* 40 */ /* long_term.c, synthesis */ word v[9] ; /* short_term.c, synthesis */ word msr; /* decoder.c, Postprocessing */ char verbose; /* only used if !NDEBUG */ char fast; /* only used if FAST */ char wav_fmt; /* only used if WAV49 defined */ unsigned char frame_index; /* odd/even chaining */ unsigned char frame_chain; /* half-byte to carry forward */ /* Moved here from code.c where it was defined as static */ word e[50] ; } ; typedef struct gsm_state GSM_STATE ; #define MIN_WORD (-32767 - 1) #define MAX_WORD 32767 #define MIN_LONGWORD (-2147483647 - 1) #define MAX_LONGWORD 2147483647 /* Signed arithmetic shift right. */ static C_INLINE word SASR_W (word x, word by) { return (x >> by) ; } /* SASR */ static C_INLINE longword SASR_L (longword x, word by) { return (x >> by) ; } /* SASR */ /* * Prototypes from add.c */ word gsm_mult (word a, word b) ; longword gsm_L_mult (word a, word b) ; word gsm_mult_r (word a, word b) ; word gsm_div (word num, word denum) ; word gsm_add (word a, word b ) ; longword gsm_L_add (longword a, longword b ) ; word gsm_sub (word a, word b) ; longword gsm_L_sub (longword a, longword b) ; word gsm_abs (word a) ; word gsm_norm (longword a ) ; longword gsm_L_asl (longword a, int n) ; word gsm_asl (word a, int n) ; longword gsm_L_asr (longword a, int n) ; word gsm_asr (word a, int n) ; /* * Inlined functions from add.h */ static C_INLINE longword GSM_MULT_R (word a, word b) { return (((longword) (a)) * ((longword) (b)) + 16384) >> 15 ; } /* GSM_MULT_R */ static C_INLINE longword GSM_MULT (word a, word b) { return (((longword) (a)) * ((longword) (b))) >> 15 ; } /* GSM_MULT */ static C_INLINE longword GSM_L_MULT (word a, word b) { return ((longword) (a)) * ((longword) (b)) << 1 ; } /* GSM_L_MULT */ static C_INLINE longword GSM_L_ADD (longword a, longword b) { ulongword utmp ; if (a < 0 && b < 0) { utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1) ; return (utmp >= (ulongword) MAX_LONGWORD) ? MIN_LONGWORD : -(longword)utmp-2 ; } ; if (a > 0 && b > 0) { utmp = (ulongword) a + (ulongword) b ; return (utmp >= (ulongword) MAX_LONGWORD) ? MAX_LONGWORD : utmp ; } ; return a + b ; } /* GSM_L_ADD */ static C_INLINE longword GSM_ADD (word a, word b) { longword ltmp ; ltmp = ((longword) a) + ((longword) b) ; if (ltmp >= MAX_WORD) return MAX_WORD ; if (ltmp <= MIN_WORD) return MIN_WORD ; return ltmp ; } /* GSM_ADD */ static C_INLINE longword GSM_SUB (word a, word b) { longword ltmp ; ltmp = ((longword) a) - ((longword) b) ; if (ltmp >= MAX_WORD) ltmp = MAX_WORD ; else if (ltmp <= MIN_WORD) ltmp = MIN_WORD ; return ltmp ; } /* GSM_SUB */ static C_INLINE word GSM_ABS (word a) { if (a > 0) return a ; if (a == MIN_WORD) return MAX_WORD ; return -a ; } /* GSM_ADD */ /* * More prototypes from implementations.. */ void Gsm_Coder ( struct gsm_state * S, word * s, /* [0..159] samples IN */ word * LARc, /* [0..7] LAR coefficients OUT */ word * Nc, /* [0..3] LTP lag OUT */ word * bc, /* [0..3] coded LTP gain OUT */ word * Mc, /* [0..3] RPE grid selection OUT */ word * xmaxc,/* [0..3] Coded maximum amplitude OUT */ word * xMc) ;/* [13*4] normalized RPE samples OUT */ void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */ struct gsm_state * S, word * d, /* [0..39] residual signal IN */ word * dp, /* [-120..-1] d' IN */ word * e, /* [0..40] OUT */ word * dpp, /* [0..40] OUT */ word * Nc, /* correlation lag OUT */ word * bc) ; /* gain factor OUT */ void Gsm_LPC_Analysis ( struct gsm_state * S, word * s, /* 0..159 signals IN/OUT */ word * LARc) ; /* 0..7 LARc's OUT */ void Gsm_Preprocess ( struct gsm_state * S, word * s, word * so) ; void Gsm_Encoding ( struct gsm_state * S, word * e, word * ep, word * xmaxc, word * Mc, word * xMc) ; void Gsm_Short_Term_Analysis_Filter ( struct gsm_state * S, word * LARc, /* coded log area ratio [0..7] IN */ word * d) ; /* st res. signal [0..159] IN/OUT */ void Gsm_Decoder ( struct gsm_state * S, word * LARcr, /* [0..7] IN */ word * Ncr, /* [0..3] IN */ word * bcr, /* [0..3] IN */ word * Mcr, /* [0..3] IN */ word * xmaxcr, /* [0..3] IN */ word * xMcr, /* [0..13*4] IN */ word * s) ; /* [0..159] OUT */ void Gsm_Decoding ( struct gsm_state * S, word xmaxcr, word Mcr, word * xMcr, /* [0..12] IN */ word * erp) ; /* [0..39] OUT */ void Gsm_Long_Term_Synthesis_Filtering ( struct gsm_state* S, word Ncr, word bcr, word * erp, /* [0..39] IN */ word * drp) ; /* [-120..-1] IN, [0..40] OUT */ void Gsm_RPE_Decoding ( /*-struct gsm_state *S,-*/ word xmaxcr, word Mcr, word * xMcr, /* [0..12], 3 bits IN */ word * erp) ; /* [0..39] OUT */ void Gsm_RPE_Encoding ( /*-struct gsm_state * S,-*/ word * e, /* -5..-1][0..39][40..44 IN/OUT */ word * xmaxc, /* OUT */ word * Mc, /* OUT */ word * xMc) ; /* [0..12] OUT */ void Gsm_Short_Term_Synthesis_Filter ( struct gsm_state * S, word * LARcr, /* log area ratios [0..7] IN */ word * drp, /* received d [0...39] IN */ word * s) ; /* signal s [0..159] OUT */ void Gsm_Update_of_reconstructed_short_time_residual_signal ( word * dpp, /* [0...39] IN */ word * ep, /* [0...39] IN */ word * dp) ; /* [-120...-1] IN/OUT */ /* * Tables from table.c */ #ifndef GSM_TABLE_C extern word gsm_A [8], gsm_B [8], gsm_MIC [8], gsm_MAC [8] ; extern word gsm_INVA [8] ; extern word gsm_DLB [4], gsm_QLB [4] ; extern word gsm_H [11] ; extern word gsm_NRFAC [8] ; extern word gsm_FAC [8] ; #endif /* GSM_TABLE_C */ /* * Debugging */ #ifdef NDEBUG # define gsm_debug_words(a, b, c, d) /* nil */ # define gsm_debug_longwords(a, b, c, d) /* nil */ # define gsm_debug_word(a, b) /* nil */ # define gsm_debug_longword(a, b) /* nil */ #else /* !NDEBUG => DEBUG */ void gsm_debug_words (char * name, int, int, word *) ; void gsm_debug_longwords (char * name, int, int, longword *) ; void gsm_debug_longword (char * name, longword) ; void gsm_debug_word (char * name, word) ; #endif /* !NDEBUG */ #endif /* PRIVATE_H */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 8bc5fdf2-e8c8-4686-9bd7-a30b512bef0c */ /* ** Copyright (C) 2001-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Version 1.3 */ /*============================================================================ ** On Intel Pentium processors (especially PIII and probably P4), converting ** from float to int is very slow. To meet the C specs, the code produced by ** most C compilers targeting Pentium needs to change the FPU rounding mode ** before the float to int conversion is performed. ** ** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It ** is this flushing of the pipeline which is so slow. ** ** Fortunately the ISO C99 specifications define the functions lrint, lrintf, ** llrint and llrintf which fix this problem as a side effect. ** ** On Unix-like systems, the configure process should have detected the ** presence of these functions. If they weren't found we have to replace them ** here with a standard C cast. */ /* ** The C99 prototypes for lrint and lrintf are as follows: ** ** long int lrintf (float x) ; ** long int lrint (double x) ; */ /* ** The presence of the required functions are detected during the configure ** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in ** the config.h file. */ #define HAVE_LRINT_REPLACEMENT 0 #if (HAVE_LRINT && HAVE_LRINTF) /* ** These defines enable functionality introduced with the 1999 ISO C ** standard. They must be defined before the inclusion of math.h to ** engage them. If optimisation is enabled, these functions will be ** inlined. With optimisation switched off, you have to link in the ** maths library using -lm. */ #define _ISOC9X_SOURCE 1 #define _ISOC99_SOURCE 1 #define __USE_ISOC9X 1 #define __USE_ISOC99 1 #elif ( defined (WIN32) || defined (_WIN32) || defined(__PLATFORM_WIN32__) || defined(__LITTLE_ENDIAN__) ) #undef HAVE_LRINT_REPLACEMENT #define HAVE_LRINT_REPLACEMENT 1 /* ** Win32 doesn't seem to have these functions. ** Therefore implement inline versions of these functions here. */ __inline long int lrint (double flt) { int intgr ; _asm { fld flt fistp intgr } ; return intgr ; } __inline long int lrintf (float flt) { int intgr ; _asm { fld flt fistp intgr } ; return intgr ; } #elif (defined (__MWERKS__) && defined (macintosh)) /* This MacOS 9 solution was provided by Stephane Letz */ #undef HAVE_LRINT_REPLACEMENT #define HAVE_LRINT_REPLACEMENT 1 #undef lrint #undef lrintf #define lrint double2int #define lrintf float2int inline int float2int (register float in) { long res [2] ; asm { fctiw in, in stfd in, res } return res [1] ; } /* float2int */ inline int double2int (register double in) { long res [2] ; asm { fctiw in, in stfd in, res } return res [1] ; } /* double2int */ #elif (defined (__MACH__) && defined (__APPLE__)) /* For Apple MacOSX. */ #undef HAVE_LRINT_REPLACEMENT #define HAVE_LRINT_REPLACEMENT 1 #undef lrint #undef lrintf #define lrint double2int #define lrintf float2int inline static long int float2int (register float in) { int res [2] ; __asm__ __volatile__ ( "fctiw %1, %1\n\t" "stfd %1, %0" : "=m" (res) /* Output */ : "f" (in) /* Input */ : "memory" ) ; return res [1] ; } /* lrintf */ inline static long int double2int (register double in) { int res [2] ; __asm__ __volatile__ ( "fctiw %1, %1\n\t" "stfd %1, %0" : "=m" (res) /* Output */ : "f" (in) /* Input */ : "memory" ) ; return res [1] ; } /* lrint */ #else #ifndef __sgi // #warning "Don't have the functions lrint() and lrintf()." // #warning "Replacing these functions with a standard C cast." #endif #define lrint(dbl) ((long) (dbl)) #define lrintf(flt) ((long) (flt)) #endif /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 42db1693-ff61-4051-bac1-e4d24c4e30b7 */ /* ** Copyright (C) 2002-2004 Erik de Castro Lopo ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU Lesser General Public License as published by ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Some defines that microsoft 'forgot' to implement. */ #ifndef S_IRWXU #define S_IRWXU 0000700 /* rwx, owner */ #endif #ifndef S_IRUSR #define S_IRUSR 0000400 /* read permission, owner */ #endif #ifndef S_IWUSR #define S_IWUSR 0000200 /* write permission, owner */ #endif #ifndef S_IXUSR #define S_IXUSR 0000100 /* execute/search permission, owner */ #endif #ifndef S_IRWXG #define S_IRWXG 0000070 /* rwx, group */ #endif #ifndef S_IRGRP #define S_IRGRP 0000040 /* read permission, group */ #endif #ifndef S_IWGRP #define S_IWGRP 0000020 /* write permission, grougroup */ #endif #ifndef S_IXGRP #define S_IXGRP 0000010 /* execute/search permission, group */ #endif #ifndef S_IRWXO #define S_IRWXO 0000007 /* rwx, other */ #endif #ifndef S_IROTH #define S_IROTH 0000004 /* read permission, other */ #endif #ifndef S_IWOTH #define S_IWOTH 0000002 /* write permission, other */ #endif #ifndef S_IXOTH #define S_IXOTH 0000001 /* execute/search permission, other */ #endif #ifndef S_ISFIFO #define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO) #endif #ifndef S_ISREG #define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG) #endif /* ** Don't know if these are still needed. ** ** #define _IFMT _S_IFMT ** #define _IFREG _S_IFREG */ /* ** Do not edit or modify anything in this comment block. ** The arch-tag line is a file identity tag for the GNU Arch ** revision control system. ** ** arch-tag: 253aea6d-6299-46fd-8d06-bc5f6224c8fe */ #endif chuck-1.2.0.8.dfsg/src/util_string.cpp0000644000175000017500000001653310600421720016203 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_string.cpp // desc: ... // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #include "util_string.h" using namespace std; //----------------------------------------------------------------------------- // name: itoa() // desc: ... //----------------------------------------------------------------------------- string itoa( t_CKINT val ) { char buffer[128]; sprintf( buffer, "%li", val ); return string(buffer); } //----------------------------------------------------------------------------- // name: ftoa() // desc: ... //----------------------------------------------------------------------------- string ftoa( t_CKFLOAT val, t_CKUINT precision ) { char str[32]; char buffer[128]; if( precision > 32 ) precision = 32; sprintf( str, "%%.%lif", precision ); sprintf( buffer, str, val ); return string(buffer); } //----------------------------------------------------------------------------- // name: tolower() // desc: ... //----------------------------------------------------------------------------- string tolower( const string & str ) { string s = str; t_CKUINT len = s.length(); // loop for( t_CKUINT i = 0; i < len; i++ ) if( s[i] >= 'A' && s[i] <= 'Z' ) s[i] += 32; return s; } //----------------------------------------------------------------------------- // name: toupper() // desc: ... //----------------------------------------------------------------------------- string toupper( const string & str ) { string s = str; t_CKUINT len = s.length(); // loop for( t_CKUINT i = 0; i < len; i++ ) if( s[i] >= 'a' && s[i] <= 'z' ) s[i] -= 32; return s; } //----------------------------------------------------------------------------- // name: trim() // desc: ... //----------------------------------------------------------------------------- string trim( const string & val ) { // two ends t_CKINT start = 0; t_CKINT end = val.length() - 1; // left trim for( start = 0; start < end; start++ ) { // non-white space if( val[start] != ' ' && val[start] != '\t' ) break; } // if start > end, then all white space if( start > end ) return ""; // right trim for( ; end >= start; end-- ) { // non-white space if( val[end] != ' ' && val[end] != '\t' ) break; } // cannot be assert( end >= start ); // return return val.substr( start, end - start + 1 ); } //----------------------------------------------------------------------------- // name: ltrim() // desc: ... //----------------------------------------------------------------------------- string ltrim( const string & val ) { // two ends t_CKINT start = 0; t_CKINT end = val.length() - 1; // left trim for( start = 0; start < end; start++ ) { // non-white space if( val[start] != ' ' && val[start] != '\t' ) break; } // if start > end, then all white space if( start > end ) return ""; // return return val.substr( start, end - start + 1 ); } //----------------------------------------------------------------------------- // name: rtrim() // desc: ... //----------------------------------------------------------------------------- string rtrim( const string & val ) { // two ends t_CKINT start = 0; t_CKINT end = val.length() - 1; // right trim for( ; end >= start; end-- ) { // non-white space if( val[end] != ' ' && val[end] != '\t' ) break; } // if end < start, then all white space if( end < start ) return ""; // return return val.substr( start, end - start + 1 ); } //----------------------------------------------------------------------------- // name: extract_args() // desc: extract argument from format filename:arg1:arg2:etc //----------------------------------------------------------------------------- t_CKBOOL extract_args( const string & token, string & filename, vector & args ) { // clear vector args.clear(); // clear filename filename = ""; // last : found pos t_CKINT prev_pos = 0; // curr : pos t_CKINT i = 0; // copy and trim string s = trim( token ); // detect t_CKBOOL scan = FALSE; t_CKBOOL ret = TRUE; char * buf = NULL; char * mask = NULL; for( i = 0; i < s.length(); i++ ) if( s[i] == '\\' ) { scan = TRUE; break; } // mad... if( scan ) { buf = new char[s.length()+1]; mask = new char[s.length()]; t_CKINT len = 0; // loop through for( i = 0; i < s.length(); i++ ) { // zero mask[len] = 0; // escape if( s[i] == '\\' && (i+1) < s.length() && s[i+1] == ':' ) { i++; mask[len] = 1; } // add buf[len++] = s[i]; } // end buf[len] = '\0'; // copy s = buf; } // loop through for( i = 0; i < s.length(); i++ ) { // look for : if( s[i] == ':' && ( !mask || !mask[i] ) ) { // sanity if( i == 0 ) { ret = FALSE; goto done; } // copy if( filename == "" ) filename = s.substr( prev_pos, i - prev_pos ); else args.push_back( s.substr( prev_pos, i - prev_pos ) ); // update prev_pos = i + 1; } } // get the remainder, if any if( prev_pos < s.length() ) { // copy if( filename == "" ) filename = s.substr( prev_pos, s.length() - prev_pos ); else args.push_back( s.substr( prev_pos, s.length() - prev_pos ) ); } done: // reclaim SAFE_DELETE_ARRAY( buf ); SAFE_DELETE_ARRAY( mask ); return ret; } chuck-1.2.0.8.dfsg/src/util_string.h0000644000175000017500000000411310600421720015637 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_string.h // desc: string functions. // // author: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // date: Summer 2005 //----------------------------------------------------------------------------- #ifndef __UTIL_STRING_H__ #define __UTIL_STRING_H__ #include "chuck_def.h" #include #include // itoa std::string itoa( t_CKINT val ); // ftoa std::string ftoa( t_CKFLOAT val, t_CKUINT precision ); // tolower std::string tolower( const std::string & val ); // toupper std::string toupper( const std::string & val ); // trim std::string trim( const std::string & val ); // ltrim std::string ltrim( const std::string & val ); // rtrim std::string rtrim( const std::string & val ); // argument extraction t_CKBOOL extract_args( const std::string & token, std::string & filename, std::vector & args ); #endif chuck-1.2.0.8.dfsg/src/util_thread.cpp0000644000175000017500000001325310600421720016140 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_thread.cpp // desc: ... // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // based on STK's XThread // Perry R. Cook + Gary Scavone // date: autumn 2004 //----------------------------------------------------------------------------- #include "util_thread.h" //----------------------------------------------------------------------------- // name: XThread() // desc: ... //----------------------------------------------------------------------------- XThread::XThread( ) { thread = 0; } //----------------------------------------------------------------------------- // name: ~XThread() // desc: ... //----------------------------------------------------------------------------- XThread::~XThread( ) { if( thread != 0 ) { #if defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) pthread_cancel(thread); pthread_join(thread, NULL); #elif defined(__PLATFORM_WIN32__) TerminateThread((HANDLE)thread, 0); #endif } } //----------------------------------------------------------------------------- // name: start() // desc: ... //----------------------------------------------------------------------------- bool XThread::start( THREAD_FUNCTION routine, void * ptr ) { bool result = false; #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) if( pthread_create( &thread, NULL, *routine, ptr ) == 0 ) result = true; #elif defined(__PLATFORM_WIN32__) unsigned thread_id; thread = _beginthreadex( NULL, 0, routine, ptr, 0, &thread_id ); if( thread ) result = true; #endif return result; } //----------------------------------------------------------------------------- // name: wait() // desc: ... //----------------------------------------------------------------------------- bool XThread::wait( long milliseconds ) { bool result = false; #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_cancel(thread); pthread_join(thread, NULL); #elif defined(__PLATFORM_WIN32__) DWORD timeout, retval; if( milliseconds < 0 ) timeout = INFINITE; else timeout = milliseconds; retval = WaitForSingleObject( (HANDLE)thread, timeout ); if( retval == WAIT_OBJECT_0 ) { CloseHandle( (HANDLE)thread ); thread = 0; result = true; } #endif return result; } //----------------------------------------------------------------------------- // name: test() // desc: ... //----------------------------------------------------------------------------- void XThread :: test( ) { #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_testcancel(); #endif } //----------------------------------------------------------------------------- // name: XMutex() // desc: ... //----------------------------------------------------------------------------- XMutex::XMutex( ) { #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_mutex_init(&mutex, NULL); #elif defined(__PLATFORM_WIN32__) InitializeCriticalSection(&mutex); #endif } //----------------------------------------------------------------------------- // name: XMutex() // desc: ... //----------------------------------------------------------------------------- XMutex::~XMutex( ) { #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_mutex_destroy( &mutex ); #elif defined(__PLATFORM_WIN32__) DeleteCriticalSection(&mutex); #endif } //----------------------------------------------------------------------------- // name: acquire() // desc: ... //----------------------------------------------------------------------------- void XMutex::acquire( ) { #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_mutex_lock(&mutex); #elif defined(__PLATFORM_WIN32__) EnterCriticalSection(&mutex); #endif } //----------------------------------------------------------------------------- // name: unlock() // desc: ... //----------------------------------------------------------------------------- void XMutex::release( ) { #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) pthread_mutex_unlock(&mutex); #elif defined(__PLATFORM_WIN32__) LeaveCriticalSection(&mutex); #endif } chuck-1.2.0.8.dfsg/src/util_thread.h0000644000175000017500000000634610600421720015612 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_thread.h // desc: ... // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // based on STK's Thread // Perry R. Cook + Gary Scavone // date: autumn 2004 //----------------------------------------------------------------------------- #ifndef __UTIL_THREAD_H__ #define __UTIL_THREAD_H__ #include "chuck_def.h" #if ( defined(__PLATFORM_MACOSX__) || defined(__PLATFORM_LINUX__) || defined(__WINDOWS_PTHREAD__) ) #include #define THREAD_TYPE typedef pthread_t THREAD_HANDLE; typedef void * THREAD_RETURN; typedef void * (*THREAD_FUNCTION)(void *); typedef pthread_mutex_t MUTEX; #define CHUCK_THREAD pthread_t #elif defined(__PLATFORM_WIN32__) #include #include #define THREAD_TYPE __stdcall typedef unsigned long THREAD_HANDLE; typedef unsigned THREAD_RETURN; typedef unsigned (__stdcall *THREAD_FUNCTION)(void *); typedef CRITICAL_SECTION MUTEX; #define CHUCK_THREAD HANDLE #endif //----------------------------------------------------------------------------- // name: struct XThread // desc: ... //----------------------------------------------------------------------------- struct XThread { public: XThread(); ~XThread(); public: // begin execution of the thread routine // the thread routine can be passed an argument via ptr bool start( THREAD_FUNCTION routine, void * ptr = NULL ); // wait the specified number of milliseconds for the thread to terminate bool wait( long milliseconds = -1 ); public: // test for a thread cancellation request. static void test( ); // clear void clear() { thread = 0; } protected: THREAD_HANDLE thread; }; //----------------------------------------------------------------------------- // name: struct XMutex // desc: ... //----------------------------------------------------------------------------- struct XMutex { public: XMutex(); ~XMutex(); public: void acquire( ); void release(void); protected: MUTEX mutex; }; #endif chuck-1.2.0.8.dfsg/src/util_xforms.c0000644000175000017500000002070510600421720015647 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_xform.c // desc: transforms // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // FFT: CARL music distribution // date: 11.27.2003 //----------------------------------------------------------------------------- #include "util_xforms.h" #include #include //----------------------------------------------------------------------------- // name: hanning() // desc: make window //----------------------------------------------------------------------------- void hanning( float * window, unsigned long length ) { unsigned long i; double pi, phase = 0, delta; pi = 4.*atan(1.0); delta = 2 * pi / (double) length; for( i = 0; i < length; i++ ) { window[i] = (float)(0.5 * (1.0 - cos(phase))); phase += delta; } } //----------------------------------------------------------------------------- // name: hamming() // desc: make window //----------------------------------------------------------------------------- void hamming( float * window, unsigned long length ) { unsigned long i; double pi, phase = 0, delta; pi = 4.*atan(1.0); delta = 2 * pi / (double) length; for( i = 0; i < length; i++ ) { window[i] = (float)(0.54 - .46*cos(phase)); phase += delta; } } //----------------------------------------------------------------------------- // name: blackman() // desc: make window //----------------------------------------------------------------------------- void blackman( float * window, unsigned long length ) { unsigned long i; double pi, phase = 0, delta; pi = 4.*atan(1.0); delta = 2 * pi / (double) length; for( i = 0; i < length; i++ ) { window[i] = (float)(0.42 - .5*cos(phase) + .08*cos(2*phase)); phase += delta; } } //----------------------------------------------------------------------------- // name: apply_window() // desc: apply a window to data //----------------------------------------------------------------------------- void apply_window( float * data, float * window, unsigned long length ) { unsigned long i; for( i = 0; i < length; i++ ) data[i] *= window[i]; } static float PI ; static float TWOPI ; void bit_reverse( float * x, long N ); //----------------------------------------------------------------------------- // name: rfft() // desc: real value fft // // these routines from the CARL software, spect.c // check out the CARL CMusic distribution for more source code // // if forward is true, rfft replaces 2*N real data points in x with N complex // values representing the positive frequency half of their Fourier spectrum, // with x[1] replaced with the real part of the Nyquist frequency value. // // if forward is false, rfft expects x to contain a positive frequency // spectrum arranged as before, and replaces it with 2*N real values. // // N MUST be a power of 2. // //----------------------------------------------------------------------------- void rfft( float * x, long N, unsigned int forward ) { static int first = 1 ; float c1, c2, h1r, h1i, h2r, h2i, wr, wi, wpr, wpi, temp, theta ; float xr, xi ; long i, i1, i2, i3, i4, N2p1 ; if( first ) { PI = (float) (4.*atan( 1. )) ; TWOPI = (float) (8.*atan( 1. )) ; first = 0 ; } theta = PI/N ; wr = 1. ; wi = 0. ; c1 = 0.5 ; if( forward ) { c2 = -0.5 ; cfft( x, N, forward ) ; xr = x[0] ; xi = x[1] ; } else { c2 = 0.5 ; theta = -theta ; xr = x[1] ; xi = 0. ; x[1] = 0. ; } wpr = (float) (-2.*pow( sin( 0.5*theta ), 2. )) ; wpi = (float) sin( theta ) ; N2p1 = (N<<1) + 1 ; for( i = 0 ; i <= N>>1 ; i++ ) { i1 = i<<1 ; i2 = i1 + 1 ; i3 = N2p1 - i2 ; i4 = i3 + 1 ; if( i == 0 ) { h1r = c1*(x[i1] + xr ) ; h1i = c1*(x[i2] - xi ) ; h2r = -c2*(x[i2] + xi ) ; h2i = c2*(x[i1] - xr ) ; x[i1] = h1r + wr*h2r - wi*h2i ; x[i2] = h1i + wr*h2i + wi*h2r ; xr = h1r - wr*h2r + wi*h2i ; xi = -h1i + wr*h2i + wi*h2r ; } else { h1r = c1*(x[i1] + x[i3] ) ; h1i = c1*(x[i2] - x[i4] ) ; h2r = -c2*(x[i2] + x[i4] ) ; h2i = c2*(x[i1] - x[i3] ) ; x[i1] = h1r + wr*h2r - wi*h2i ; x[i2] = h1i + wr*h2i + wi*h2r ; x[i3] = h1r - wr*h2r + wi*h2i ; x[i4] = -h1i + wr*h2i + wi*h2r ; } wr = (temp = wr)*wpr - wi*wpi + wr ; wi = wi*wpr + temp*wpi + wi ; } if( forward ) x[1] = xr ; else cfft( x, N, forward ) ; } //----------------------------------------------------------------------------- // name: cfft() // desc: complex value fft // // these routines from CARL software, spect.c // check out the CARL CMusic distribution for more software // // cfft replaces float array x containing NC complex values (2*NC float // values alternating real, imagininary, etc.) by its Fourier transform // if forward is true, or by its inverse Fourier transform ifforward is // false, using a recursive Fast Fourier transform method due to // Danielson and Lanczos. // // NC MUST be a power of 2. // //----------------------------------------------------------------------------- void cfft( float * x, long NC, unsigned int forward ) { float wr, wi, wpr, wpi, theta, scale ; long mmax, ND, m, i, j, delta ; ND = NC<<1 ; bit_reverse( x, ND ) ; for( mmax = 2 ; mmax < ND ; mmax = delta ) { delta = mmax<<1 ; theta = TWOPI/( forward? mmax : -mmax ) ; wpr = (float) (-2.*pow( sin( 0.5*theta ), 2. )) ; wpi = (float) sin( theta ) ; wr = 1. ; wi = 0. ; for( m = 0 ; m < mmax ; m += 2 ) { register float rtemp, itemp ; for( i = m ; i < ND ; i += delta ) { j = i + mmax ; rtemp = wr*x[j] - wi*x[j+1] ; itemp = wr*x[j+1] + wi*x[j] ; x[j] = x[i] - rtemp ; x[j+1] = x[i+1] - itemp ; x[i] += rtemp ; x[i+1] += itemp ; } wr = (rtemp = wr)*wpr - wi*wpi + wr ; wi = wi*wpr + rtemp*wpi + wi ; } } // scale output scale = (float)(forward ? 1./ND : 2.) ; { register float *xi=x, *xe=x+ND ; while( xi < xe ) *xi++ *= scale ; } } //----------------------------------------------------------------------------- // name: bit_reverse() // desc: bitreverse places float array x containing N/2 complex values // into bit-reversed order //----------------------------------------------------------------------------- void bit_reverse( float * x, long N ) { float rtemp, itemp ; long i, j, m ; for( i = j = 0 ; i < N ; i += 2, j += m ) { if( j > i ) { rtemp = x[j] ; itemp = x[j+1] ; /* complex exchange */ x[j] = x[i] ; x[j+1] = x[i+1] ; x[i] = rtemp ; x[i+1] = itemp ; } for( m = N>>1 ; m >= 2 && j >= m ; m >>= 1 ) j -= m ; } } chuck-1.2.0.8.dfsg/src/util_xforms.h0000644000175000017500000000503210600421722015652 0ustar piempiem/*---------------------------------------------------------------------------- ChucK Concurrent, On-the-fly Audio Programming Language Compiler and Virtual Machine Copyright (c) 2004 Ge Wang and Perry R. Cook. All rights reserved. http://chuck.cs.princeton.edu/ http://soundlab.cs.princeton.edu/ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 U.S.A. -----------------------------------------------------------------------------*/ //----------------------------------------------------------------------------- // name: util_xform.h // desc: transforms // // authors: Ge Wang (gewang@cs.princeton.edu) // Perry R. Cook (prc@cs.princeton.edu) // FFT - from CARL distribution // date: 11.27.2003 //----------------------------------------------------------------------------- #ifndef __UTIL_XFORM_H__ #define __UTIL_XFORM_H__ #include // c linkage #if defined(_cplusplus) || defined(__cplusplus) extern "C" { #endif // complex type typedef struct { float re ; float im ; } complex; // polar type typedef struct { float modulus ; float phase ; } polar; // complex absolute value #define cmp_abs(x) ( sqrt( (x).re * (x).re + (x).im * (x).im ) ) #define __modulus(x) cmp_abs(x) #define __phase(x) ( atan2((double)(x).re, (double)(x).im) ) #define FFT_FORWARD 1 #define FFT_INVERSE 0 #define make_window hanning // make the window void hanning( float * window, unsigned long length ); void hamming( float * window, unsigned long length ); void blackman( float * window, unsigned long length ); // apply the window void apply_window( float * data, float * window, unsigned long length ); // real fft, N must be power of 2 void rfft( float * x, long N, unsigned int forward ); // complex fft, NC must be power of 2 void cfft( float * x, long NC, unsigned int forward ); // c linkage #if ( defined( __cplusplus ) || defined( _cplusplus ) ) } #endif #endif chuck-1.2.0.8.dfsg/THANKS0000644000175000017500000000110010600421722013242 0ustar piempiemChucK THANKS: Many people have further contributed to ChucK by suggesting great new ideas and improvements, reporting problems, or submitting actual code. Here is a list of these people. Help us keep it complete and exempt of errors. ThanK you! (also see AUTHORS) Andrew Appel Brian Kernighan Dan Trueman Matt Hoffman Ken Steiglitz Paul Lansky n++k Nick Collins Niklas Werner Szymon Rusinkiewicz Paul Calammia Tom Briggs Matt Shanley Adam Wendt Gary Scavone Graham Coleman Kassen Scott Smallwood Mark Daly Stacken Princeton Graphics Group ChucK Users Community! --- chuck-1.2.0.8.dfsg/TODO0000644000175000017500000000067710600421722013041 0ustar piempiem TODO: --- Fully implement garbage collector! Fix static data! Add file support! Add protected/private! Put stdout and chout back! Add OpenGL API (almost there) - GlucK Add automatic type resolution Add more unit generators - import more filters - FFT/DCT/DWT - analysis - Marsyas - File support Add more tutorials Add net language support Performance enhancement Improve documentation too many to name. Need more developers. Thanks. chuck-1.2.0.8.dfsg/VERSIONS0000644000175000017500000010126410600421722013536 0ustar piempiem--- 1.2.0.8 - (added) command line argument support e.g. %> chuck foo.ck:1:hello bar:2.5:"with space" also works with OTF commands e.g. %> chuck + foo:1:yo also works with Machine.add( ... ) e.g. // code Machine.add( "foo:1:2:yo" ); (see examples/basic/args.ck for accessing from code) - (added) OS X: watchdog enabled win32: watchdog implemented and enabled (combats chuck infinite empty loop implosion) - (added) OTF server/listener now ON by default... to enable, specify --loop or --server to disable, specify --standalone - (added) new UGens: -------- Dynamics: dynamics processor (compressor, expander, etc.) (author Matt Hoffman and Graham Coleman) (see examples/special/) GenX: classic + new lookup table functions base class (author Dan Trueman, ported from RTCMix) (see examples/special/) float .lookup( float ) : lookup table value float[] .coeffs( float[] ) : load the table Gen5 (extends GenX) Gen7 (extends GenX) Gen9 (extends GenX) Gen10 (extends GenX) Gen17 (extends GenX) CurveTable (extends GenX) WarpTable (extends GenX) LiSa: (Li)ve (Sa)mpling! (author Dan Trueman, partly based on Dan's munger~) -------- - (added) (prototype) string catenation (for now will leak memory! use wisely!!!) e.g. // expression "a" + "b" "a" + 45 "a" + 5.1 "postfix" +=> str; - (added) string escape sequences \0 \n \t \a \" \b \f \r \v \\ \nnn (3 digit octal ascii) - (added) new Objects: -------- StringTokenizer: uh string tokenizer (by whitespace) (use to be hidden PRC object) see examples/string/token.ck ConsoleInput: interim console input (until file I/O) (use to be hidden Skot object) see examples/string/readline.ck -------- - (api) API additions -------- (also see API modifications below) ADSR: dur attackTime() dur decayTime() dur releaseTime() WvOut: void closeFile() Hid: void openTiltSensor() int read( int, int, HidMsg ) HidMsg: int isWheelMotion() (support for mouse scroll wheels) int key (cross-platform USB HID Keyboard Usage code) int ascii (ASCII value of key, where appropriate) -------- - (api) API modifications (sorry!) -------- ADSR: float attackTime( float ) -> dur attackTime( dur ) float decayTime( float ) -> dur decayTime( dur ) float releaseTime( float ) -> dur releaseTime( dur ) -------- - (api) deprecated --> new classes -------------------------- HidIn --> Hid - (fixed) adc.last() now returns correct value (was returning 0) - (fixed) array is now subclass of Object - (fixed) accessing null array no longer crashes (instead: exception) - (fixed) allow: 0 length float arrays - (fixed) check for negative array size - (fixed) accessing null map no longer crashes (instead: exception) - (fixed) connecting null UGen references no longer crashes - (fixed) trivial (null == null) no longer evaluated as string - (fixed) strict (x,y) => z type checking - (fixed) UGens no longer able to make duplicate connections - (fixed) && now terminates early if an operand evaluates to 0 || terminates early if an operand evaluates to 1 - (fixed) bug accessing static members of built-in classes - (fixed) OscSend.startMsg no longer silently fails when using a single string message specification - (fixed) Math.atan2 now accepts the proper arguments - (fixed) increased OTF command network fail-safe measures - (fixed) STK BlitSquare now produces correct frequency (applied fix from STK release) - (fixed) no longer spontaneously crashes when HidIn and other event based input mechanisms are firing rapidly - (fixed) using non-static variables from inside static functions - (fixed) variables must be declared before being used --- 1.2.0.7b - added: (all) HidIn.name() now returns meaningful device name - fixed: (all) fixed STK Envelope bug - fixed: (osx) mouse motion now correctly returns delta Y - fixed: (win32) joystick hat messages now properly reported - fixed: (win32) fixed bug where joysticks of same model/product id would send messages through the same HidIn object - fixed: (all) seg fault in OSCSend.startMsg() with single string message specification --- 1.2.0.7 - (api) deprecated --> new classes -------------------------- sinosc --> SinOsc triosc --> TriOsc sqrosc --> SqrOsc sawosc --> SawOsc pulseosc --> PulseOsc phasor --> Phasor osc --> Osc noise --> Noise cnoise --> CNoise impulse --> Impulse step --> Step halfrect --> HalfRect fullrect --> FullRect gain --> Gain zerox --> ZeroX delayp --> DelayP sndbuf --> SndBuf pan2 --> Pan2 mix2 --> Mix2 onepole --> OnePole onezero --> OneZero polezero --> PoleZero twopole --> TwoPole twozero --> TwoZero biquad --> BiQuad **** --> **** std --> Std math --> Math machine --> Machine -------------------------- - (added) --deprecate:X flag X can be stop, warn, or ignore - default is warn - (added) STK BiQuad get functions pfreq, prad, zfreq, zrad - (added) ADSR functions: void .set( dur a, dur d, float s, dur r ); void .set( float a, float d, float s, float r ); - (added) new UGens (adapted from SC3 Server, Pure Data, CSound) -------------------------- LPF : resonant lowpass filter (2nd order butterworth) HPF : resonant highpass filter (2nd order butterworth) BPF : bandpass filter (2nd order butterworth) BRF : bandreject filter (2nd order butterworth) ResonZ : resonant filter (BiQuad with equal-gain zeros) FilterBasic : base class to above filters -------------------------- - (added) new HidIn static variables for HidMsg message and device types - (added) HidMsg fields to determine device type and number - (added) HidMsg functions with capitalization rather than underscores (underscored functions deprecated) - (added) .period for all oscillators - (fixed) floating point denormals no longer cause potentially massive CPU usage on intel processors, this includes BiQuad, OnePole, TwoPole, PoleZero, JCRev, PRCRev, NRev - (fixed) STK Echo.max no longer gives incorrect warnings - (fixed) linux makefiles now respects CC/CFLAGS/CXX (Cedric Krier) - (fixed) SinOsc/TriOsc/PulseOsc/SqrOsc/Phasor.sync now unified: .sync == 0 : sync frequency to input .sync == 1 : sync phase to input .sync == 2 : fm synth | NOTE: the above changes may break/affect existing patches using TriOsc, PulseOsc, or SqrOsc - (fixed) TriOsc/PulseOsc/SqrOsc phase consistent with convention - (fixed) ADSR now handles keyOff() before sustain state - (fixed) ADSR now correctly inherits Envelope --- 1.2.0.6 (more) - (added) support for Mac OS X universal binary - (added) executable now reports targets: > chuck --version chuck version: 1.2.0.6 (dracula) exe target: mac os x : universal binary http://chuck.cs.princeton.edu/ --- 1.2.0.6 - (added) support for Mac OS X on Intel: (make osx-intel) - (added) win32 - boost thread priority default from 0 to 5 - (added) Mandolin.bodyIR( string path ): set body impulse response - (added) HID: support for mouse input on OS X, Windows, Linux through 'HidIn' class - (added) HID: support for keyboard input on OS X, Windows through 'HidIn' class - (added) new HID examples: hid/mouse-fm.ck /keyboard-flute.ck - (added) OS X: --probe human-readable MIDI names (thanks to Bruce Murphy) - (fixed) multiple declarations now behave correctly: (example: int a, b, c;) - (fixed) now possible to spork non-static member functions (example: Foo foo; spork ~ foo.go();) - (fixed) sporking fixed in general - (fixed) pre/post ++/-- now work correctly (example: int i; <<< i++ + i++ * ++i >>>;) - (fixed) public classes can now internally reference non-public classes in the same file - (fixed) obj @=> obj now ref counts correctly - (fixed) STK Mandolin.detune( float f ) changed - (fixed) STK Mandolin.damping( float f ) changed --- 1.2.0.5b - (fixed) adc bug - (fixed) %=> bug --- 1.2.0.5 - (added) multi-channel audio - use --channels or -c set number of channels for both input and output - use --out/-o and --in/-i to request # of input and output channels separately - stereo is default (for now) - (added) UGen.channels() - (added) class UGen -> class UGen_Multi -> class UGen_Stereo - (added) UGen UGen_Multi.chan( int ) use this to address individual channels - (added) examples in examples/multi - n.ck : n channels detuned sine - i.ck : n channels impulse - (added) HID support (author: Spencer Salazar) - (added) 'HidIn' event class (see examples/hid/*.ck) - (added) Terminal Keyboard Input (immediate mode, separate from HID) - (added) 'KBHit' event class (see examples/event/kb*.ck) - (added) sndbuf.chunks : better real-time behavior - can be set to arbitrary integers (before the .read happens) - default is 0 frames (no chunk) - set .chunks to 0 to read in entire file (previous behavior) - (added) int math.isinf( float ) // infinity test - (added) int math.isnan( float ) // NaN test (see examples/basic/infnan.ck) - (added) sndbuf.valueAt( int ) for returning sample at arbitrary pos (see examples/basic/valueat.ck) - (added) MASSIVE STK UPDATE - (added) 'StkInstrument' class .noteOn( float ) .noteOff( float ) .freq( float ) / .freq() .controlChange( int, float ) - (added) the following now extend 'StkInstrument' (most of them have additional parameters) - BandedWG - BlowBotl - BlowHole - Bowed - Brass - Clarinet - Flute - FM (and all its subclasses: BeeThree, FMVoices, HevyMetl, PercFlut, Rhodey, TubeBell, Wurley) - Mandolin - ModalBar - Moog - Saxofony - Shakers - Sitar - StifKarp - VoicForm - (added) better STK documentation http://chuck.cs.princeton.edu/doc/program/ugen.html - (added) examples/stk/modulate.ck - (added) --watchdog and --nowatchdog flags (very experiment watchdog for real-time audio) - (added) () => function; // calls function(); (thanks to Mike McGonagle for reporting) - (added) if exp: ( cond ? if_cond : else_cond ) (thanks to Mike McGonagle for reporting) - (added) math.abs( int ), math.fabs( float ), math.sgn( float ) (std version unchanged) - (added) new examples - basic/infnan.ck /fm.ck fm2.ck fm3.ck /valueat.ck - event/kb.ck kb2.ck - hid/joy.ck /joy-fm.ck /joy-noise.ck /joy-shake.ck - multi/i.ck /n.ck /we-robot.ck - osc/s.ck /r.ck - stk/bandedwg.ck /blowbotl.ck /blowhole.ck /bowed.ck /brass.ck /clarinet.ck /flute.ck /mandolin.ck /modalbar.ck /saxofony.ck /stifkarp.ck - (fixed) sinsoc, triosc, sqrosc, phasor: - .sync( 0 ) uses input signal to modulate frequency - .sync( 2 ) uses input signal to modulate phase (FM synthesis) - (fixed) impulse.last() no longer has extra samp delay (thanks to Mike McGonagle for reporting) - (fixed) class inheritance now handles the first overloaded function of a parent correctly when called using a subclass instance. in other words, this part sucks less now. (thanks to Mike McGonagle for reporting) - (fixed) (internal) type checker re-instantiation patched - (fixed) (internal) detach_all() moved to chuck_globals.cpp - (fixed) (internal) global variables moved to chuck_globals.cpp - (fixed) file handles close in compiler and parser - (fixed) syntax error causing syntax errors --- 1.2.0.4 - (added) The ChucK Manual (pdf) fantastic work by Adam Tindale and other documentors see doc/Chuck_manual.pdf - (added) Envelope.duration( dur ), Envelope.duration() - (added) Envelope.keyOn(), Envelope.keyOff(); - (added) PitShift.mix( float ), PitShift.mix() (originally effectMix) - (added) std.srand( int ) : seed random number generator - (added) update to RtAudio 3.2.0 -> much lower latency: Window DS (thanks to Gary Scavone and Robin Davies) - (added) update to RtMidi 1.0.4 -> improved midi: linux ALSA (thanks to Gary Scavone and Pedro Lopez-Cabanillas) - (added) bandlimited ugens: Blit, BlitSaw, BlitSquare (thanks to Robin Davies for implementation, Gary Scavone for putting them in STK) - (added) examples/basic/foo.ck foo2.ck tick.ck tick2.ck (foo2 shows using Blit, tick.ck is a simple counter) - (added) examples/class/dinky.ck try.ck (creating and using class to make instruments) - (fixed) sndbuf.read now closes file handle and sets curf - (fixed) default bufsize=256 under OSX and 512 under all other - (fixed) chuck + foof garbled error message - (fixed) chuck.lex compatibility under some linux - (fixed) waiting on null event: no longer crashes VM - (fixed) function arguments: no longer allow reference to primitive types - (fixed) function: correctly select overloaded functions w/ implicit cast - (fixed) std.atoi() std.atof(): no longer crash on null string - (fixed) std.fabs(): now works correctly - (fixed) basic/moe.ck larry.ck currly.ck use fabs - (fixed) missing base class virtual destructors; FreeBSD/g++ compatibility (thanks rasmus) - (fixed) most -Wall warnings - (fixed) CK_LOG_SYSTEM_ERROR now CK_LOG_CORE --- 1.2.0.3 (API changes again) (syntax change - 'loop' -> 'repeat') - loop( ... ) construct (see 1.2.0.2) changed to repeat( ... ) - usage and semantics same as before - this is also an experimental language feature (let us know if it's good or bad) - float std.abs( float ) changed -> int std.abs( int ) - use std.fabs( ... ) for floating point absolute value - (added) /* block comments */ - no nesting allowed - closing '*/' not necessary if commenting out rest of the file - (fixed) arrays of null object references correctly allocated : Event @ events[128]; - (fixed) DEFAULT sndbuf rate now set correctly to interpolate for files outside of chuck sample rate (no longer have to explicit do 1 => buf.rate) - (fixed) examples/midi/polyfony*.ck no longer creates 128 unnecessary events... - (changed) examples/stk/wurley.ck -> examples/stk/wurley2.ck - (changed) examples/stk/wurley.ck (wacky version) --- 1.2.0.2 - 2005.10.17 (sorry for the API changes) - (API change) OSC_Send class name changed to 'OscSend' (also): .startMesg(...) name changed to startMsg(...) - (API change) OSC_Recv class name changed to 'OscRecv' - (API change) OSC_Addr class name changed to 'OscEvent' (also): .hasMesg() name changed to .hasMsg() (also): .nextMesg() name changed to .nextMsg() - (API change) STK Shakers.freq now expect Hz instead of MIDI number - (moved) examples/event/opensound*.ck moved to examples/osc/OSC*.ck (see OSC_send.ck and OSC_recv.ck for examples on OpenSoundControl) - (moved) examples/event/polyfony*.ck to examples/midi/ - (added) 'loop(...){ }' control structure : example: loop( 8 ) { ... } // executes body 8 times example: loop( foo ) { ... } // executes body foo times (foo is evaluated exactly once entering the loop, the value at that time is used as a constant to control loop iteration - even if foo is changed in the loop body.) - supports break and continue - important: one fundamantal difference between the loop semantic and for/while/until semantic is that the argument expression 'exp' in loop( exp ) is evaluated exactly once when the loop is first entered. - (added) MidiIn and MidiOut member functions: .good() : whether the thing is good to go (int) .num() : the device number (int) .name() : the device name (string) .printerr( int ) : whether to auto print errors (default YES) - (added) --version command line flag (Graham) - (changed) chuck --status now prints shreds sorted by id (previously it was the current shreduling order + blocked) - (changed) a udp port may now be shared by many OSC_Recv (phil) : the incoming messages are broadcast to all - (changed) address/type string in OSC: comma now optional (phil) - (fixed) events are now 0-sample synchronous (instead of 1) - (fixed) startup audio stability for --callback mode - (fixed) incorrect 'continue' behavior in for loops - (fixed) improved OSC stability (phil) - (fixed) OSC shreduling sanity check failed now resolved - (fixed) math.round for negative numbers (win32) - (fixed) std.mtof and std.ftom now internally double precision - (fixed) removed extra console output in STK Flute - (fixed) multiple delete/assertion failure on type rollback - (fixed) chuck --kill now closes WvOut and MidiRW file handles - (added) examples/midi/gomidi.ck : very useful sometimes - (added) examples/midi/gomidi2.ck - (added) examples/basic/rec-auto.ck (rec2.ck back in action) - (added) examples/basic/fmsynth.ck (from v1) - (added) examples/sitar.ck - (fixed) examples/stk/*-o-matic.ck now uses array --- 1.2.0.1 - 2005.9.27 - (added) full callback capability for real-time audio - blocking functionality still available - select via flags: --blocking and --callback - improves latency and stability, especially on linux - use --callback (default) for low latency / small buffer size - use --blocking for higher throughput - (fixed) crash when doing on-the-fly 'replace' : chuck --replace 0 foo.ck - (fixed) OSC event function now correctly named ("event") - (fixed) removed debug output in OSC - (fixed) implicit cast is now correct when sporking (thanks to Manfred Brockhaus) - (fixed) examples code reformatted, cleaned, and commented - (fixed) nested class definitions can now have same name as outer class - (fixed) nested class bug in scan1 (thanks to Robin Davies) - (fixed) variable resolution in parent class now visible (thanks to Robin Davies) - (fixed) variable resolution ordering - local, class, parent, global (thanks to Robin Davies) - (fixed) emitter now asserts inheritance instead of equality (thanks to Robin Davies) - (fixed) string comparison ==, != - (added) string operations <, <=, >, >= --- 1.2.0.0 SYNTAX and OPERATORS: - (added) +=>, operator : 2 +=> i; (also) -=>, *=>, /=>, %=> - (added) @=> for explicit assignment this is the only way to make object reference assignments - (added) implicit int to float casting - (changed) cast now look like: 1.1 $ (int) => int i; - (added) function call by chucking : // call (1,4) => math.rand2f => result; // same as math.rand2f(1,4) => result; LANGUAGE: - (fixed) type system for existing types - (added) forward lookup of classes and functions (mutual recursion) - (added) stack overflow detection for massive recursion DOCUMENTATION: - (added) language specification: http://chuck.cs.princeton.edu/doc/language COMMAND-LINE: - (added) --probe prints all audio and MIDI devices - (added) --log or --verbose logs compiler and virtual machine - (added) --logN or --verboseN multi level logging 1 - least verbose 10 - most verbose OBJECTS: - (added) 'class' definitions : class X { int i; } - (added) 'extends' keyword : class Y extends Event { int i; } - (added) virtual/polymorphic inheritance - (added) added pre-constructors - code at class level gets run when object is instantiated - (added) function overloading : class X { fun void foo() { } fun void foo( int y ) { } } - (added) base classes (can be extended): Object, Event, UGen see below - (added) base classes (cannot be extended): array, string see below - (added) member data - (added) static data - (added) member functions - (added) static functions EVENTS: - (added) base Event class : Event e; can be used directly can be extended to custom events (see one_event_many_shreds.ck) - (added) waiting on event, chuck to now : e => now; // wait on e - (added) e.signal() wakes up 1 shred, if any - (added) e.broadcast() wakes up all shreds waiting on e - (added) class MidiEvent (see gomidi2.ck) alternative to polling. - (added) class OSCEvent ARRAYS: - (added) arrays : int a[10]; float b[20]; Event e[2]; - (added) multidimensional arrays : int a[2][2][2]; - (added) associative arrays : int a[10]; 0 => a["foo"]; all arrays are both int-indexed and associative - (added) array initialization : [ 1, 2, 3 ] @=> int a[]; - (added) .cap() for array capacity - (added) .find() test if item is associative array - (added) .erase() erase item in associative array UGENS: - (added) class UGen can be extended - (changed) all ugen parameters are now also functions: // set freq 440 => s.freq => val; // same as... s.freq( 440 ) => val; - (changed) left-most parameters must now be called as functions // no longer valid f.freq => float val; // valid f.freq() => float val; // still ok 440 => s.freq => float val; SHREDS: - (added) class Shred - (added) .yield() .id() STRINGS: - (added) class string AUDIO: - (added) stereo all stereo unit generators have .left, .right, .pan functions - (changed) stereo ugen: dac (2 in, 2 out) - (changed) stereo ugen: adc (0 in, 2 out) - (added) stereo ugen: pan2 take mono or stereo input and pans - (added) stereo ugen: mix2 mix stereo input into mono --- 1.1.5.6 - 2005.4.11 - last 1.1 release : contains all 1.1 changes --- 1.1.5.5 - 2005.2.10 - FIFO to RR for audio and synthesis - improves stability on OS X - fixed stack underflow emitter bug with declarations - fixed cpu sleep bug on win32 --- 1.1.5.4 - 2004.11.18 - fixed clicks when using adc unit generator (thanks to paul botelho for testing) - added 'maybe' keyword maybe == 0 or 1, with 50% probability each new examples: - maybe.ck : the maybe keyword - bad idea? maybe. - maybecli.ck : maybe click, maybe not adc examples work better: - adc.ck - echo.ck - i-robot.ck --- 1.1.5.3 - 2004.11.4 - when a shred is removed from VM, all children shreds are also recursively removed (this fix crash due to removing shreds with active children shreds) (to keep children around, put parent in infinite time-loop) (this isn't always good - real solution coming soon) - 'start' keyword now available - holds the a shred's begin time updated examples: - powerup.ck : start local variable changed name - spork.ck : added infinite time loop to keep children active --- 1.1.5.2 - 2004.10.17 - crtical patch shreduler time precision - same as 1.1.5.1 - see below --- 1.1.5.1 - 2004.10.15 - on-the-fly chuck files to remote hosts! > chuck @hostname + foo.ck > chuck @hostname -p + foo.ck - TCP replacing UDP for commands - endian observed (mac <-> win32/linux) - more sensible VM output for on-the-fly commands - many on-the-fly bug fixes - --replace: new shred inherits the replaced shred id (useful to keep track of shreds in VM) - sndbuf automatically set .rate to 1.0 (instead of 0.0) (0.0 => buf.rate if no play on next time advance) - new on-the-fly examples new examples: - otf_*.ck - illustrates precise on-the-fly timing (adapted from Perry's ChucK drumming + Ge's sine poops) chuck them one by one into the VM: terminal 1%> chuck --loop terminal 2%> chuck + otf_01.ck (wait) terminal 2%> chuck + otf_02.ck (wait) (repeat through otf_07.ck) (remove, replace and add your own) --- 1.1.5.0 - 2004.9.29 - now able to write audio files (wav, aiff, raw) (try rec.ck and rec2.ck concurrently with any other shreds to record to disk) - STK file endian is now observed (more things should work on little endian systems) - added 4 "special" built-in sound samples "special:glot_pop" - glottal pulse (flat) "special:glot_ahh" - glottal 'ahh' pop "special:glot_eee" - glottal 'eee' pop "special:glot_ooo" - glottal 'ooo' pop (see/listen to moe++.ck, larry++.ck, curly++.ck) - all bulit-in sound samples now loadable from both WaveLoop and sndbuf - (win32) sndbuf now properly loads wav aiff new examples: - moe++.ck - stooges, evolved - larry++.ck - curly++.ck - rec.ck - run this concurrently to write audio to file (also try with -s flag for file out, no real-time audio) - rec2.ck - same as rec, but writes to different file every time, for sessions --- 1.1.4.9 - 2004.9.18 - all of STK is now in ChucK! - new examples (see below) - add '--bufnum' to chuck command line (number of buffers) - --status no longer prints full path for source - full path now works for command line + (thanks Adam T.) - minor bug fixes - improved online ugen documentation (go phil!) new ugens: (again, thanks to Phil Davidson!) BandedWG (STK) Blowhole (STK) BlowBotl (STK) Bowed (STK) Brass (STK) Clarinet (STK) Flute (STK) ModalBar (STK) Saxofony (STK) Sitar (STK) StifKarp (STK) delayp - variable write position delay line new examples: band-o-matic.ck - banded waveguide, automated delayp.ck - shows usage mode-o-matic.ck - modal bar, happy chaos stifkarp.ck - stifkarp, chaos --- 1.1.4.8 - 2004.9.8 - added win32 visual studio support (chuck_win32.*) - new oscillators (see below, thanks to Phil) - corrected more issues on some 64-bit systems - new examples (see below) - chucking to oscillators now able to control phase (alternative to doing FM by hand (1::samp at a time), see pwm.ck and sixty.ck) (thanks to Phil) new ugens: triosc - triangle wave pulseosc - pulse wave oscillator w/ controllable pulse width sqrosc - square wave sawosc - saw tooth phasor - 0 to 1 ramp new examples: sixty.ck - shows osc's pwm.ck - basic pulse width modulation (you can still do FM "by hand" - see fmsynth.ck) --- 1.1.4.7 - 2004.9.4 - improved performance (reduce cpu overhead) - fixed bug that caused crash on ctrl-c - added sndbuf.play (same as rate) - corrected issues on some 64-bit systems - sndbuf.ck now works --- 1.1.4.6 - 2004.8.26 - added netin/netout unit generators (alpha version) - added a lot of STK unit generators (thanks to philipd) (over 80% of STK is now imported) - fixed Shakers (thanks to philipd) : examples/shake-o-matic.ck - better compilation for cygwin - minor bugs fixes - added many READ functionality for ugen parameters see online documentation at: http://chuck.cs.princeton.edu/doc/program/ugen.html new ugens: - netout (alpha version) - audio over UDP (see net_send.ck) - netin (alpha version) - audio over UDP (see net_recv.ck) - Chorus (STK) - Envelope (STK) - NRev (STK) - PRCRev (STK) - Modulate (STK) - PitShift (STK) - SubNoise (STK) - WvIn (STK) - WvOut (STK) - BlowBotl (STK) - FM group (STK) - BeeThree - FMVoices - HevyMetl - PercFlut - TubeBell new examples: - shake-o-matic.ck - STK shakers going bonkers - net_send.ck - oneway sender - net_recv.ck - oneway recv - net_bounce.ck - redirect --- 1.1.4.5 - 2004.8.14 - fixed bug for multiple declarations - made functions local to shred by default - shadowing now works - add 'blackhole' ugen for ticking ugens - added std.mtof (philipd) - added std.ftom - added std.dbtorms - added std.rmstodb - added std.dbtopow - added std.powtodb new ugens: - blackhole - the silent sample sucker - Wurley (STK) - Rhodey (STK) - OnePole (STK) - OneZero (STK) - PoleZero (STK) - TwoPole (STK) - TwoZero (STK) new examples: - powerup.ck ( (ab)use of TwoPole and sporking) - i-robot (building feedback filters) - voic-o-form.ck (music for replicants) - rhodey/wurley.ck (more stk-o-matics) --- 1.1.4.4 - 2004.8.2 - added sndfile patch for jack/sndfile (Martin Rumori) - added special raw wav for WaveLoop (philipd, gewang) (see examples/dope.ck) "special:ahh" "special:eee" "special:ooo" "special:britestk" "special:dope" "special:fwavblnk" "special:halfwave" "speical:impuls10" "special:impuls20" "special:impuls40" "special:mand1" "special:mandpluk" "special:marmstk1" "special:peksblnk" "special:ppksblnk" "special:slience" "speical:sineblnk" "special:sinewave" "special:snglpeak" "special:twopeaks" - fixed shred shreduling ID bug for on-the-fly added shreds (gewang) - fixed function resolution for on-the-fly added shreds (gewang) - added math.nextpow2( int n ) (Niklas Werner, gewang) new STK ugens: - Mandolin (see examples/mandolin.ck examples/mand-o-matic.ck) - Moog (see examples/moogie.ck) new examples: - mandolin.ck (use of STK mandolin) - mand-o-matic (fire it up!) - dope.ck (Homer's WaveLoop using internal STK sound) - print_last.ck (prints last ugen output) - wind2.ck (2 shreds control parameters) --- 1.1.4.3 - 2004.7.4 - add sndfile support (Ari Lazier) - add sndbuf file reading/writing (Ari Lazier) - add sinosc.sfreq and phase (Phil Davidson) - add sndbuf rate and sinc interp (Phil Davidson) - add cget functions for unit generators parameters (many parameters are readable now) - add .last for last sample computed for all ugen's - add constants in lib import - add math.pi math.twopi math.e - add --srate(N) in command line (chuck --help) - typing .ck extension optional on command line - fixed spork bug involved local variables - fixed nested function calls - fixed math.min/max bug (Phil Davidson) - fixed audio stability OS X (Ari Lazier) - fixed MidiOut issue (thanks to n++k) new Unit Generators (from STK) ADSR (updated) BiQuad Delay DelayA DelayL Echo WaveLoop (updated) --- 1.1.4.2 - 2004.6.14 - added support for arbitrary audio in/out (via command line) --- 1.1.4.1 - 2004.6.13 - double lt gt fix - added demo[0-5].ck to examples - PROGRAMMER updated - big/little endian issue fixed --- 1.1.4.0 - 2004.6.12 - major update to use double float for time, dur, and float (this fixes the millisecond bug) --- 1.1.3.6 - 2004.6.9 - fixed win32 build problem (thanks to Adam Wendt) - fixed midi stack problem (thanks to Thomas Charbonnel) --- 1.1.3.5 - 2004.6.8 - fixed mem stack bug (report Alex Chapman) - added jack support (thanks to Thomas Charbonnel) --- 1.1.3.4 - 2004.6.7 - fixed spork bug - bad midiin now returns 0 - supports sound card with no input - add spork.ck --- 1.1.3.3 - 2004.6.7 - added ability to spork shreds from code - casting float/int - 0-127 MIDI devices support - fix bugs in on-the-fly commands - added features to --add, --remove - added --time --kill - fixed table bug (thanks to n++k) - fixed linux makefile (thanks to n++k) - added STK ugen: WaveLoop, Shakers, JCRev, ADSR - added shred-time synch by T - (now % T ) => now; --- 1.1.3.2 --- 1.1.3.1 --- 1.1.3.0 - initial release